Frage

Ich habe vor kurzem damit begonnen, AutoFixture+AutoMoq zu verwenden und versuche, eine Instanz davon zu erstellen Func<IDbConnection> (d. h. eine Verbindungsfabrik).

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

Das scheint ziemlich gut zu funktionieren:

  1. Mein zu testendes System kann den Delegaten aufrufen und erhält einen Schein davon IDbConnection
  2. Auf dem kann ich dann anrufen CreateCommand, was mir einen Eindruck davon verschaffen wird IDbCommand
  3. Auf dem kann ich dann anrufen ExecuteReader, was mir einen Eindruck davon verschaffen wird IDataReader

Ich möchte jetzt zusätzliche Setups am Modell durchführen IDataReader, wie zum Beispiel, dass es zurückkommt true Wann Read() wird genannt.

Nach dem, was ich gelesen habe, sollte ich es verwenden Freeze dafür:

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

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

Dies scheint jedoch nicht meinen Erwartungen zu entsprechen.Wenn ich anrufe IDbCommand.ExecuteReader, bekomme ich einen anderen Reader als den, den ich gerade eingefroren/eingerichtet habe.

Hier ist ein Beispiel:

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

Was mache ich falsch?Wie bekomme ich andere Vorrichtungen, wie z IDbCommand, um die simulierte Instanz von zu verwenden IDataReader?

War es hilfreich?

Lösung

Ab 3.20.0 können Sie verwenden AutoConfiguredMoqCustomization.Dadurch werden alle Mocks automatisch so konfiguriert, dass die Rückgabewerte ihrer Mitglieder von AutoFixture generiert werden.

Z.B., IDbConnetion.CreateCommand wird automatisch so konfiguriert, dass ein zurückgegeben wird IDbCommand von der Vorrichtung und IDbCommand.ExecuteReader wird automatisch so konfiguriert, dass ein zurückgegeben wird IDataReader aus der Vorrichtung.

Alle diese Tests sollten jetzt bestanden werden:

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

Andere Tipps

Du musst Freeze Die Mock<IDbCommand> auch – und richten Sie das Scheinobjekt (als Stub) ein, um das Vorhandene zurückzugeben dataReaderMock.Object Beispiel.

Wenn Sie der Phase „Anordnen“ Ihres Tests Folgendes hinzufügen, wird der Test bestanden:

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

Obwohl die Lösung von Nikos funktioniert, würde ich nicht empfehlen, sich über ado.net lustig zu machen.

Meiner Meinung nach werden Ihre Tests wahrscheinlich schwer zu verstehen und zu warten sein und Ihnen nicht das Vertrauen geben, das Ihre Tests Ihnen geben sollten.

Ich würde in Betracht ziehen, Ihre Datenschicht zu testen, indem Sie bis zur Datenbank vorgehen, auch wenn diese langsamer ist.

Ich würde empfehlen, diesen Artikel über Best Practices zum Spotten zu lesen:http://codebetter.com/jeremymiller/2006/01/10/best-and-worst-practices-for-mock-objects/

Machen Sie sich nicht über andere lustig:http://aspiringcraftsman.com/2012/04/01/tdd-best-practices-dont-mock-others/

Ich kenne Ihre genaue Situation nicht, aber ich wollte Ihnen das trotzdem mitteilen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top