2013-07-23 49 views
1

我有一個帶有兩個Map字段的抽象類。我想嘲笑並注入一個AbstractClass的子類的對象來進行單元測試。另一個我真的不太在意,但它有一個固定器。使用mockito的@InjectMocks解決setter注入問題

public abstract class AbstractClass { 
    private Map<String, Object> mapToMock; 
    private Map<String, Object> dontMockMe; 

    private void setDontMockMe(Map<String, Object> map) { 
     dontMockMe = map; 
    } 
} 

當使用@InjectMocks時,它會自動嘗試按順序注入:構造函數,設置器,字段。它通過檢查類型來檢查它是否可以在每個地方注入,然後命名是否存在多種類型的可能性。這對我來說效果不好,因爲我的嘲弄的mapToMock實際上是通過它的setter注入到dontMockMe中的。我無法編輯這個抽象類。有什麼辦法可以避免二傳注射嗎?先謝謝你!

+1

只是爲了糾正你寫的東西 - Mockito首先嚐試構造函數注入,然後嘗試「setter和field」注入,其中mock可以通過setter或直接注入到字段中。即使你沒有這個二傳手,你仍然會遇到問題,因爲Mockito會將你的模擬注入到這兩個領域。 –

回答

3

那麼這是一個角落的情況下,自動注射將不會在目前設計的Mockito注射的方式工作。當有多個相同類型的字段時,Mockito也會遇到一些缺點。


因此,要理解爲什麼這是行不通讓我們深入一點的方式的Mockito執行注射:

  1. 它會嘗試通過構造函數注入注入依賴,如果成功它贏得」爲了保護新創建的實例免受最終的副作用的影響,請嘗試以下步驟。

  2. 那麼,如果構造函數注入沒有發生(無參數的構造函數,或對象已實例化),然後將的Mockito尋找嘲笑和setter之間的匹配。但它必須做出一些選擇才能自動發生。

    1. 如果只有A類型的模擬,只有一個二傳手與A類型,然後setter注入會發生。

    2. 如果有多個或者嘲笑或A類型的制定者會試圖找到使用類型和模擬(通常是@Mock字段名)的名稱相匹配。如果找到匹配,則會發生注射。

  3. 然後,如果仍有一些嘲笑離開注射,字段注入可能發生,使用相同的算法與二傳:

    1. 如果只有類型的模擬A只有一個字段類型A則會發生字段注入。

    2. 如果有多個模擬或類型爲A的字段,它將嘗試使用模擬的類型和名稱(通常爲@Mock字段名稱)來查找匹配項。如果找到匹配,則會發生注射。


目前你的代碼是停留在2.1階段,大概是因爲只有一個模擬可用。

就目前Mockito的實現來說,沒有真正優雅的解決方案,有必要自己寫入注入代碼。這實際上是Mockito注射的要點,如果注射過於複雜或奇怪,那麼您將不得不寫出來;編寫這個樣板代碼實際上是質疑當前設計的最佳工具。

Mockito注射是真正爲簡單,直的設計而設計的。

在我看來,我覺得不對:

  1. 嘲笑一個Map,你沒有自己的類型,這可能會導致很多問題。
  2. 只能模擬測試對象中的單個地圖,這意味着您的測試對測試對象的內部工作知之甚多。

如果您重構代碼並使協作者出現,這將有益於設計。有了清晰的依賴關係/合作者,它肯定會使注射更清晰。此外,測試的重點應放在與合作者的交互上,而不是數據如何實現,數據只應作爲結果對給定輸入進行測試。