2011-11-02 47 views
3

我對要測試的對象有相當重要的依賴關係圖。解決我的依賴問題最簡單的方法是什麼,而無需在任何地方註冊mocks?在大型依賴對象圖上注入模擬

例如,我有一個依賴關係圖如下:

PublicApi 
    ApiService 
     AccountingFacade 
     BillingService 
      BillingValidation 
      BillingRepository 
     UserService 
      UserRepository 

我想測試PublicApi.CreateUser(),我希望它通過所有的代碼運行,但我想嘲笑倉庫所以我不不得不向數據庫寫入任何內容。我應該只使用一個DI容器並註冊我的所有服務,並使用mock替換存儲庫,然後解析PublicApi並運行該方法?

我正在研究AutoFixture,看起來它可能能夠處理這樣的事情,但我無法將自己的頭圍繞整個'Freeze'與'Register'並且它與Moq集成。

回答

5

對於Unittests,您應該只模擬直接依賴關係。在你的情況下,你創建PublicApi併爲ApiService注入一個模擬,並驗證PublicApi是否在ApiService模擬上使用正確的值調用適當的方法。

以同樣的方式測試所有其他與更深層依賴關係隔離的組件。

如果你想測試幾個組件的組合,那不是單元測試,而是集成測試。因此,這取決於你如何將你的課程放在一起。例如如果您使用的是IoC容器,則可能支持以某種方式替換存儲庫的配置。在這種情況下,您可以使用應用程序的配置並使用mock替換存儲庫以及潛在的視圖。

+0

這是有道理的。我可以通過進行多層測試來獲得全面覆蓋,而不是一次測試多個層。 – scottm

+0

確切地說,它使得測試本身更簡單,更易於理解。 –

+0

+1,直接點。 –

1

這可能沒有什麼幫助,但我會說無論如何。

看來你試圖一次測試太多,爲什麼不只是測試BillingService-> BillingValidation,然後是BillingService-> BillingRepository等。這樣你將有一套測試證明每個測試都能正常工作,那麼當你在PublicApi Layer上,你只需要模擬ApiService,因爲你已經測試了它下面的所有東西,所以再次測試它沒有任何價值。

一般我只會一次測試1層,但我不知道你的完整場景,所以你可能有些東西我沒有考慮到,所以如果是這種情況,你真的需要測試所有這一切我只會帶入一個簡單輕量級的DI框架,比如Ninject或其他東西。

這樣你就可以將所有的類型綁定到mock上,然後從你的PublicApi上實例化。

隨着ninject它看起來是這樣的:

Kernel.Bind<UserRepository>.ToConst(YourMockUserRepositoryInstance); 
Kernel.Bind<UserService>.ToConst(YourMockUserServiceInstance); 
Kernel.Bind<BillingRepository>.ToConst(YourMockBillingRepositoryInstance); 
Kernel.Bind<BillingValidation>.ToConst(YourMockBillingValidationInstance); 
Kernel.Bind<BillingService>.ToConst(YourMockBillingServiceInstance); 
Kernel.Bind<AccountingFacade>.ToConst(YourMockAccountingFacadeInstance); 
Kernel.Bind<ApiService>.ToConst(YourMockApiServiceInstance); 
Kernel.Bind<PublicApi>.ToSelf(); 

var publicApi = Kernel.Get<PublicApi>(); 

雖然你要問自己,你在這裏的測試?如果我只是首先提到它,我會這樣做,如果它更多的話可能會考慮後者的選擇。無論哪種方式,我希望它給你一些選擇。