tag propiedad fuente documentar como codigo c# autofixture

c# - propiedad - No se puede comprender la diferencia entre Freeze/Inject/Register



propiedad tag c# (3)

Modifiqué tu prueba (que no afirma nada actualmente, por cierto) y si realizas su ejecución, verás una línea de OrderLine con "Foo" cuando su valor de miembro de la línea privada se inyecte en el Order .

Tenía otra versión de la prueba en la que agregué propiedades de solo lectura para OrderLine en Order and Name en OrderLine para que pudiera hacer afirmaciones sobre estos objetos, pero eso no es ni aquí ni allí.

Esta prueba configura el dispositivo utilizando el método FromFactory directamente, que a veces puede ser útil:

[Fact] public void MethodName() { var fixture = new Fixture().Customize(new AutoMoqCustomization()); const string expected = "Foo"; fixture.Customize<OrderLine>(o => o .FromFactory(() => new OrderLine(expected))); var order = fixture.Create<Order>(); }

Antes de comenzar, soy un gran admirador de AutoFixture, todavía estoy en la curva de aprender a usar la herramienta. Así que gracias por haber desarrollado Autofixture Mr Ploeh y todos los colaboradores.

Comencemos con mi pregunta

Según AutoFixture / AutoMoq ignora la instancia inyectada / simulacro congelado

La parte interesante del enlace de arriba tiene este código

Mock<ISettings> settingsMock = new Mock<ISettings>(); settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString); ISettings settings = settingsMock.Object; fixture.Inject(settings);

A lo que Mark responde puede ser reescrito para

fixture.Freeze<Mock<ISettings>>() .Setup(s => s.Get(settingKey)).Returns(xmlString);

Parece un azúcar sintáctico, el método Freeze es una forma de escribir en una interfaz fluida la creación del simulacro, la configuración y la inyección en el contenedor de autofixture.

Después de hacer algunas investigaciones en la web, en realidad hay una diferencia funcional entre Freeze e Inject. Encontré esta pregunta: https://github.com/AutoFixture/AutoFixture/issues/59 que señalan la respuesta a ¿Cómo puedo congelar una instancia nula en AutoFixture?

El autor del enlace de arriba describe el método Freeze como el siguiente:

Internamente, Freeze crea una instancia del tipo solicitado (por ejemplo, IPayPalConfiguration) y luego la inyecta para que siempre devuelva esa instancia cuando la solicite de nuevo

Entiendo que cuando lo hacemos

var customer = fixture.Freeze<Order>();

siempre usará la misma instancia de pedido siempre que nuestro código solicite un tipo de orden. Pero, ¿qué sucede si especifico en el constructor Freeze que quiero que use una instancia específica?

Aquí hay un pequeño ejemplo de código:

[Fact] public void MethodeName() { var fixture = new Fixture().Customize(new AutoMoqCustomization()); fixture.Freeze<OrderLine>(new OrderLine("Foo")); var order = fixture.Create<Order>(); } public class Order { private readonly OrderLine _line; public Order(OrderLine line) { _line = line; } } public class OrderLine { private readonly string _name; public OrderLine(string name) { _name = name; } }

¿No debería el nombre de OrderLine ser igual a "Foo" en lugar de namefe48163a-d5a0-49a5-b349-7b11ba5f804b? La documentación del método Freeze dice:

<typeparam name="T">The type to freeze.</typeparam> <param name="fixture">The fixture.</param> <param name="seed">Any data that adds additional information when creating the anonymous object. Hypothetically, this value might be the value being frozen, but this is not likely.</param>

¿Por qué el autor no está seguro de cuándo se devuelve el valor? Si especifico, mi instancia en el constructor de Freeze, estoy esperando que autofixture use esta instancia?

entonces

Tenga en cuenta que no es probable que se use como el valor congelado, a menos que haya personalizado para hacerlo. Si desea inyectar un valor específico en el dispositivo, debe usar el método en su lugar.

Parece que tengo que personalizar el parámetro de semilla. ¿Alguien puede aclarar? La solución apuntada por la documentación es usar el método Inject. Y de hecho, funciona en mi ejemplo de código con OrderLine.

Estoy buscando su ayuda para entender la diferencia entre Inmovilizar, Inyectar, y también Registrar que, de acuerdo con el código fuente, simplemente se llama por el método de Inyección pero toma una lambda.


Freeze , Inject y Register todos están personalizando el algoritmo de creación.

Con Inject y Register está especificando explícitamente que un objeto debe crearse de una manera particular, en su ejemplo suministrando una new OrderLine("Foo") manualmente.

Con Freeze no especifica cómo se debe crear un objeto; pide a AutoFixture que le proporcione una instancia.

Al final, todos los métodos anteriores usan la misma API de nivel inferior:

fixture.Customize<T>(c => c.FromFactory(creator).OmitAutoProperties());

La razón por la cual fixture.Freeze<OrderLine>(new OrderLine("Foo")); no crea una instancia de OrderLine con el valor de OrderLine especificado porque de forma predeterminada se ignora la inicialización .

Para favorecer los valores de SeedFavoringRelay<T> de un tipo particular, puede crear un SeedFavoringRelay<T> :

public class SeedFavoringRelay<T> : ISpecimenBuilder where T : class { public object Create(object request, ISpecimenContext context) { if (context == null) throw new ArgumentNullException("context"); var seededRequest = request as SeededRequest; if (seededRequest == null || !seededRequest.Request.Equals(typeof(T))) return new NoSpecimen(request); var seed = seededRequest.Seed as T; if (seed == null) return new NoSpecimen(request); return seed; } }

Entonces puedes usarlo de la siguiente manera:

fixture.Customizations.Add( new SeedFavoringRelay<OrderLine>()); fixture.Freeze<OrderLine>(new OrderLine("Foo")); // -> Now fixture.Create<Order>() creates an Order with OrderLine''s Name = "Foo".


Registrarse e Inyectar

Érase una vez, no hubo Inject ni Freeze ; Register reguló el código.

En aquel entonces, había una sobrecarga de Register así definida:

public static void Register<T>(this IFixture fixture, T item)

Sin embargo, tenía que compartir la API con este pariente cercano:

public static void Register<T>(this IFixture fixture, Func<T> creator)

El creador de AutoFixture pensó que esto era bueno, pero por desgracia: los usuarios se vieron afectados por la confusión. Lo más grave es que un usuario podría escribir:

fixture.Register(() => universe.LightUp());

pero también

fixture.Register(universe.LightUp);

lo que significa exactamente lo mismo, porque universe.LightUp es una referencia a un método, y por lo tanto coincide con un delegado.

Sin embargo, esa sintaxis parece una referencia de propiedad, por lo que si LightUp hubiera sido una propiedad en lugar de un método, la primera sobrecarga sería seleccionada por el compilador.

Esto causó mucha confusión, por lo que la sobrecarga Register<T>(this IFixture fixture, T item) se renombró a Inject<T>(this IFixture fixture, T item) .

Congelar

Freeze tiene una historia diferente. Hace mucho tiempo, cuando todavía usaba AutoFixture de manera imperativa, noté que repetidamente escribía código como este:

var foo = fixture.Create<Foo>(); fixture.Inject(foo);

Entonces decidí que este era un concepto y lo llamé Freeze . El método Freeze es solo una abreviatura para esas dos líneas de código.

Estoy buscando su ayuda para entender la diferencia entre Inmovilizar, Inyectar, y también Registrarse que, de acuerdo con el código fuente, se llama simplemente por el método Inject pero toma una lambda

En general, no debería ser demasiado difícil distinguir entre Inject y Register , ya que sus firmas no colisionan. Por lo tanto, si intentas lograr un objetivo con uno de esos dos métodos y tu código se compila, probablemente elijas la versión correcta.

Este también sería el caso de Freeze si no fuera por la sobrecarga utilizada en el OP:

[EditorBrowsable(EditorBrowsableState.Never)] public static T Freeze<T>(this IFixture fixture, T seed)

Tenga en cuenta que esta sobrecarga en realidad tiene EditorBrowsableState.Never , porque siempre confunde a las personas. Sin embargo, a pesar de eso, aparentemente la gente todavía encuentra esa sobrecarga, por lo que creo que debería moverse en AutoFixture 4 . Es una de esas características que existen porque fue fácil de implementar ...