Pregunta

Recientemente comencé a usar AutoFixture+AutoMoq y estoy intentando crear una instancia de Func<IDbConnection> (es decir, una fábrica de conexiones).

var fixture = new Fixture().Customize(new AutoMoqCustomization());
var connectionFactory = fixture.Create<Func<IDbConnection>>();

Esto parece funcionar bastante bien:

  1. Mi sistema bajo prueba puede llamar al delegado y se burlará de él. IDbConnection
  2. al que luego puedo llamar CreateCommand, lo que me hará burlarse de IDbCommand
  3. al que luego puedo llamar ExecuteReader, lo que me hará burlarse de IDataReader

Ahora quiero realizar configuraciones adicionales simulando IDataReader, como hacer que regrese true cuando Read() se llama.

Por lo que he leído, debería usar Freeze para esto:

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();

dataReaderMock.Setup(dr => dr.Read())
                      .Returns(true);

Aunque esto no parece cumplir mis expectativas.cuando llamo IDbCommand.ExecuteReader, obtendré un lector diferente al que acabo de congelar/configurar.

He aquí un ejemplo:

var fixture = new Fixture().Customize(new AutoMoqCustomization());

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
              .Returns(true);

//true - Create<IDataReader> retrieves the data reader I just mocked
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDataReader>());

//false - IDbCommand returns a different instance of IDataReader
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());

¿Qué estoy haciendo mal?¿Cómo consigo otros accesorios, como IDbCommand, para usar la instancia simulada de IDataReader?

¿Fue útil?

Solución

A partir de 3.20.0, puedes usar AutoConfiguredMoqCustomization.Esto configurará automáticamente todos los simulacros para que AutoFixture genere los valores de retorno de sus miembros.

P.ej., IDbConnetion.CreateCommand se configurará automáticamente para devolver un IDbCommand del aparato, y IDbCommand.ExecuteReader se configurará automáticamente para devolver un IDataReader del aparato.

Todas estas pruebas deberían pasar ahora:

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
              .Returns(true);

//all pass
Assert.Same(dataReaderMock.Object, fixture.Create<IDataReader>());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbConnection>().CreateCommand().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<Func<IDbConnection>>()().CreateCommand().ExecuteReader());

Otros consejos

Tienes que Freeze el Mock<IDbCommand> también – y configurar el objeto simulado (como un Stub) para devolver el existente dataReaderMock.Object instancia.

Si agrega lo siguiente a la fase Organizar de su prueba, la prueba pasará:

var dbCommandStub = 
    fixture
        .Freeze<Mock<IDbCommand>>()
        .Setup(x => x.ExecuteReader())
        .Returns(dataReaderMock.Object);

Mientras que la solución de Nikos funciona, no lo recomendaría a burlarse de ado.net.

En mi opinión, sus pruebas probablemente serán difíciles de entender, mantener y no le darán la confianza que sus pruebas deberían darle.

Consideraría probar su capa de datos al pasar todo el camino a la base de datos a pesar de que es más lento.

Recomendaría leer este artículo con respecto a las mejores prácticas para burlarse: http://codebetter.com/Jeremymiller / 2006/01/10 / Best-Peor-Peor-Peor-Pretty-for-Mock-Objects /

No te burles de otros: http://aspiringcraftsman.com/2012/04/01 / TDD-BEST-PRÁCTICAS-DONT-MOFE-OTROS /

No sé su situación exacta, pero de todos modos quería compartir esto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top