Al inyectar dos instancias concretas, la segunda instancia anula la primera.
Al inyectar una instancia concreta, seguida de una instancia simulada, la segunda instancia no anula la primera.
Esto hace que la idea de realizar algunas pruebas que usen un simulacro y algunas pruebas que usen una implementación (usando un constructor de clases de prueba para compartir un accesorio entre las pruebas) sea bastante incómoda.
Al inyectar dos instancias concretas, la segunda instancia anula la primera.
Al inyectar una instancia concreta, seguida de una instancia simulada, la segunda instancia anula la primera.
`` C #
usando System.Collections.Generic;
usando AutoFixture;
usando AutoFixture.AutoMoq;
usando Moq;
usando Xunit;
espacio de nombres SomeNamespace
{
AutoFixtureTests de clase pública
{
[Hecho]
// Pases
public void Should_OverridePreviouslyInjectedString ()
{
const string test1 = "test1";
const string test2 = "test2";
var fixture = new Fixture();
fixture.Inject(test1);
fixture.Inject(test2);
Assert.Equal(fixture.Create<string>(), test2);
}
[Fact]
// Fails
public void Should_OverridePreviouslyInjectedInstance()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var sut1 = new List<int>();
fixture.Inject<IList<int>>(sut1);
fixture.Freeze<Mock<IList<int>>>();
var sut2 = fixture.Create<IList<int>>();
Assert.NotSame(sut1, sut2);
}
}
}
''
Hola @ charles-salmon,
Gracias por tomarse el tiempo para informar esto.
El comportamiento que está observando es _por diseño_. Permíteme explicarte. 🙂
Si observa la implementación del método Freeze<T>
:
var value = fixture.Create<T>();
fixture.Inject(value);
return value;
Verá que todo lo que está haciendo es crear una muestra de T
e inyectarla en el dispositivo. De hecho, el método Freeze
surgió como un atajo útil para esta misma operación. Como escribió @ploeh en su publicación en la que presentó el método Freeze en 2010:
Resultó que usamos tanto este idioma de codificación que decidimos encapsularlo en un método de conveniencia. Después de un poco de debate, llegamos al nombre Freeze, porque básicamente congelamos una sola variable anónima en el dispositivo, omitiendo el algoritmo predeterminado para crear nuevas instancias.
Dado eso, no debería sorprender que congelar el mismo tipo T
como una instancia inyectada produzca la misma instancia.
Ahora, para abordar su punto:
Esto hace que la idea de realizar algunas pruebas que usen un simulacro y algunas pruebas que usen una implementación (usando un constructor de clases de prueba para compartir un accesorio entre las pruebas) sea bastante incómoda.
Dado que un dispositivo representa el _contexto_ en el que se ejecuta una prueba, ciertamente _ puede_ tener varias pruebas que compartan el mismo dispositivo ; sin embargo, esto tiene el costo de mezclar múltiples preocupaciones, y posiblemente conflictivas.
El libro xUnit Patterns lo resume muy bien :
El mayor problema con un dispositivo compartido es que puede provocar "colisiones" entre las pruebas, lo que posiblemente resulte en pruebas erráticas , ya que las pruebas pueden depender de los resultados de otras pruebas. Otro problema es que un accesorio diseñado para servir muchas pruebas seguramente será mucho más complicado que el accesorio mínimo necesario para una sola prueba.
Esta "colisión" es exactamente lo que sucede cuando una prueba espera que un objeto de tipo T
sea una instancia específica, mientras que otra prueba espera que T
sea un objeto falso .
Como no puedo pensar en un escenario de prueba en el que tenga sentido que el mismo tipo T
sea un simulacro _y_ una instancia concreta (aunque estoy feliz de que se demuestre que estoy equivocado), sugiero que tenga estos Las pruebas utilizan diferentes accesorios, cada uno configurado para servir a su escenario particular.
Comentario más útil
Hola @ charles-salmon,
Gracias por tomarse el tiempo para informar esto.
El comportamiento que está observando es _por diseño_. Permíteme explicarte. 🙂
Si observa la implementación del método
Freeze<T>
:Verá que todo lo que está haciendo es crear una muestra de
T
e inyectarla en el dispositivo. De hecho, el métodoFreeze
surgió como un atajo útil para esta misma operación. Como escribió @ploeh en su publicación en la que presentó el método Freeze en 2010:Dado eso, no debería sorprender que congelar el mismo tipo
T
como una instancia inyectada produzca la misma instancia.Ahora, para abordar su punto:
Dado que un dispositivo representa el _contexto_ en el que se ejecuta una prueba, ciertamente _ puede_ tener varias pruebas que compartan el mismo dispositivo ; sin embargo, esto tiene el costo de mezclar múltiples preocupaciones, y posiblemente conflictivas.
El libro xUnit Patterns lo resume muy bien :
Esta "colisión" es exactamente lo que sucede cuando una prueba espera que un objeto de tipo
T
sea una instancia específica, mientras que otra prueba espera queT
sea un objeto falso .Como no puedo pensar en un escenario de prueba en el que tenga sentido que el mismo tipo
T
sea un simulacro _y_ una instancia concreta (aunque estoy feliz de que se demuestre que estoy equivocado), sugiero que tenga estos Las pruebas utilizan diferentes accesorios, cada uno configurado para servir a su escenario particular.