Domanda

Ho recentemente iniziato a utilizzare AutoFixture + AutomoQ e sto provando a creare un'istanza di Func<IDbConnection> (I.e., una fabbrica di connessione).

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

Questo sembra funzionare piuttosto bene:

    .
  1. Il mio sistema sotto test può chiamare il delegato e riceverà un finto di IDbConnection
  2. su cui posso chiamare CreateCommand, che mi prenderà una presa di IDbCommand
  3. su cui posso chiamare ExecuteReader, che mi prenderà una presa di IDataReader
  4. Voglio ora eseguire ulteriori configurazioni sulla finzione di IDataReader, ad esempio renderlo restituito true quando viene chiamato Read().

    Da quello che ho letto, dovrei usare Freeze per questo:

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

    Questo non sembra di soddisfare le mie aspettative però. Quando chiamo IDbCommand.ExecuteReader, riceverò un lettore diverso da quello che ho appena congelato / configurazione.

    Ecco un esempio:

    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());
    
    .

    Cosa sto facendo male? Come posso ottenere altri dispositivi, come IDbCommand, per utilizzare l'istanza deriso di IDataReader?

È stato utile?

Soluzione

A partire da 3.20.0, è possibile utilizzare AutoConfiguredMoqCustomization.Questo configurerà automaticamente tutti i guasti in modo che i valori di ritorno dei membri siano generati da AutoFixture.

E.G., IDbConnetion.CreateCommand verrà automaticamente configurato per restituire un IDbCommand dal dispositivo, e IDbCommand.ExecuteReader verrà automaticamente configurato per restituire un IDataReader dal dispositivo.

Tutti questi test dovrebbero passare ora:

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());
.

Altri suggerimenti

Devi anche generarecodicitagcode anche il Freeze e configurano l'oggetto finto (come stub) per restituire l'istanza Mock<IDbCommand> esistente.

Se si aggiunge quanto segue alla fase dell'oggetto del test, il test passerà:

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

Mentre la soluzione da Nikos funziona, non vorrei non raccomandare ADO.net.

Secondo me, i tuoi test saranno probabilmente difficili da capire, mantenere e non ti darà la fiducia che i tuoi test dovrebbero darti.

Considererei il test del tuo livello di dati andando fino al database anche se è più lento.

Consiglierei di leggere questo articolo riguardante le migliori pratiche per il beffardo: http://codebetter.com/jeremymymiller / 2006/01/10 / Best-and-peggiore-pratiche-Practice-per-mock-oggetti /

Non prendere in giro gli altri: http://aspiringcraftsman.com/2012/04/01 / TDD-Best-Practices-DONT-DROCK-Altri /

Non conosco la tua situazione esatta ma comunque volevo condividere questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top