2014-11-24 33 views
0

我試圖爲具有下面的構造函數的定義(運行實際應用時充滿Ninject)的ASP.NET創建單元測試:是否有必要模擬單元測試中的所有依賴項?

public OrderController(IViewModelFactory modelFactory, INewsRepository repository, ILoggedUserHelper loggedUserHelper, 
     IDelegateHelper delegateHelper, ICustomerContextWrapper customerContext) { 
     this.factory = modelFactory; 
     this.loggedUserHelper = loggedUserHelper; 
     this.delegateHelper = delegateHelper; 
     this.customerContext = customerContext; 
    } 

我想測試OrderController裏面的方法,但爲了隔離它,我必須嘲笑所有這些依賴關係,這完全是荒謬的(也許也必須模仿依賴關係)。

在這種情況下,這是單元測試這個類的最佳做法嗎?

謝謝。

+0

只是嘲笑所有四個注入的依賴關係。如果你不使用Moq,它應該讓嘲笑變得更容易。 – 2014-11-24 11:48:58

+0

我使用Moq來模擬這些依賴關係(或者至少這是我的意圖) – 2014-11-24 11:49:43

+0

嘲笑我們感興趣的四個依賴項的原因是什麼?據推測,你只需要在每個模擬對象上設置一個或兩個方法? – Chris 2014-11-24 11:51:05

回答

2

那麼,你必須提供測試雙打所有的依賴關係,不一定是嘲笑。

幸運的是,這是21世紀,有工具可以讓我們的工作更輕鬆。您可以使用AutoFixture創建OrderController的實例,並根據需要注入mock。

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization()); 
var orderController = fixture.Create<OrderController>(); 

其中,基本上等同於:

var factory = new Mock<IViewModelFactory>(); 
var repository = new Mock<INewsRepository>(); 
var delegateHelper = new Mock<IDelegateHelper >(); 
var customerContext = new Mock<ICustomerContextWrapper >(); 

var orderController = new OrderController(factory.Object, repository.Object, delegateHelper.Object, customerContext.Object); 

如果這些依賴依賴於其他類型的,這些都被設定爲好。具有AutoConfiguredMoqCustomization定製的AutoFixture將構建完整的依賴關係圖。

如果您需要訪問存儲庫模擬,那麼您可以稍後再做一些額外的設置或斷言,您可以將其凍結它。凍結類型將使fixture容器包含該類型的只有一個實例,例如:

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization()); 
var repositoryMock = fixture.Freeze<Mock<INewsRepository>>(); 
repositoryMock.Setup(x => x.Retrieve()).Returns(1); 

//the frozen instance will be injected here 
var orderController = fixture.Create<OrderController>(); 

repositoryMock.Verify(x => x.Retrieve(), Times.Once); 

我使用起訂量在這些例子中,但AutoFixture也與NSubstitute,RhinoMock和FOQ集成。

披露:我是該項目的貢獻者之一

+0

這很有趣,我可以自定義那些自動生成的嘲笑,以防我需要嗎?方法調用/屬性/這些嘲諷返回的是什麼? – 2014-11-24 12:01:02

+1

@DavidJiménezMartínez是的,你可以使用'Freeze'。我在我的文章中添加了一個示例,介紹如何進行其他設置。這個定製將設置所有模擬的成員,如:mockObject.Setup(x => x.Id).Returns(fixture.Create ())''。基本上,燈具會自動調用它自己,直到創建完整的依賴關係圖。 – dcastro 2014-11-24 12:06:53

+1

檢查[作弊表](https://github.com/AutoFixture/AutoFixture/wiki/Cheat-Sheet)(雖然有些過時,但仍然有用)。此外,如果您不希望自動混合自動爲您設置模擬,則可以使用「AutoMoqCustomization」自定義,而不是僅僅注入閃亮的全新模擬。 – dcastro 2014-11-24 12:09:04

1

不,你不知道。您可以使用的測試對象實現的不同概念稱爲「測試雙重測試」。嘲笑是由傑拉德·梅薩羅斯在his book定義只是一個類型的測試雙:

  • 虛擬對象被傳來傳去,但從來沒有實際使用。通常它們只是用來填充參數列表。
  • 假的對象實際上有工作的實現,但通常採取一些快捷方式,使他們不適合生產(一個InMemoryTestDatabase是一個很好的例子)。
  • 存根提供對測試過程中調用的罐裝答案,通常對測試以外的任何內容都沒有響應。
  • Spies是根據他們被稱爲如何記錄一些信息的存根。其中一種形式可能是一個電子郵件服務,記錄它發送的郵件數量。
  • 模擬預先編程與期望形成預期接收的呼叫的規範。如果他們收到他們不期望的電話並在驗證過程中進行檢查以確保他們獲得了他們期望的所有電話,他們可以拋出異常。

您只需按照要求爲您的測試通過儘可能多的存根,假貨和假人。

傻瓜幾乎沒有工作來生成,可能足以涵蓋您的方案。一個例子是使用IEmailer和ILogWriter的構造函數。如果您只測試Log方法,則只需提供足夠的IEmailer實現,以便測試不會拋出參數異常。

另外,關於你關於子依賴關係的觀點...... Moq會爲你處理這個問題,因爲你的接口的Moq實現不會依賴於依賴關係。

相關問題