簡體   English   中英

使用AutoFixture模擬依賴項

[英]Mocking a dependency with AutoFixture

我最近開始使用AutoFixture + AutoMoq,我正在嘗試創建一個Func<IDbConnection>的實例(即連接工廠)。

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

這看起來效果很好:

  1. 我的測試系統可以調用委托,它將獲得IDbConnection的模擬
  2. 然后,我可以調用CreateCommand ,這將讓我模擬IDbCommand
  3. 然后,我可以調用ExecuteReader ,這將讓我模擬IDataReader

我現在想要在IDataReader的模擬上執行其他設置,例如在調用Read()時使其返回true

根據我的閱讀,我應該使用Freeze

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

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

這似乎不符合我的期望。 當我調用IDbCommand.ExecuteReader ,我會得到一個不同於我剛凍結/設置的讀者。

這是一個例子:

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

我究竟做錯了什么? 如何使用其他燈具(如IDbCommand )來使用IDataReader的模擬實例?

從3.20.0開始,您可以使用AutoConfiguredMoqCustomization 這將自動配置所有模擬,以便其成員的返回值由AutoFixture生成。

例如, IDbConnetion.CreateCommand將自動配置為從fixture返回IDbCommand ,並且IDbCommand.ExecuteReader將自動配置為從fixture返回IDataReader

所有這些測試現在應該通過:

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

您還必須Freeze Mock<IDbCommand> - 並設置模擬對象(作為Stub)以返回現有的dataReaderMock.Object實例。

如果將以下內容添加到測試的編配階段,測試將通過:

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

雖然Nikos的解決方案有效,但我不建議嘲笑ado.net。

在我看來,您的測試可能很難理解,維護並且不會讓您對測試給您的信心。

我會考慮通過一直到數據庫來測試你的數據層,即使它比較慢。

我建議閱讀這篇關於模擬最佳實踐的文章: http//codebetter.com/jeremymiller/2006/01/10/best-and-worst-practices-for-mock-objects/

不要嘲笑他人: http//aspiringcraftsman.com/2012/04/01/tdd-best-practices-dont-mock-others/

我不知道你的確切情況,但無論如何我想分享這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM