2012-10-03 93 views
2

我使用Mockito單元測試業務對象。業務對象使用通常從數據庫獲取數據的DAO。爲了測試業務對象,我意識到,這是更容易使用一個單獨的內存DAO(而保持一個HashMap中的數據),而不是寫的所有部分嘲笑被認爲是不好的做法? (Mockito)

when(...).thenReturn(...) 

語句。要創建這樣一個DAO,我開始局部嘲笑我的DAO接口,像這樣:

when(daoMock.getById(anyInt())).then(new Answer() { 
    @Override 
    public Object answer(InvocationOnMock invocation) throws Throwable { 
     int id = (Integer) invocation.getArguments()[0]; 
     return map.get(id); 
    } 
}); 

,但它發生,我認爲它只是實現了一個全新的DAO實現自己較容易(使用內存中的HashMap)甚至沒有使用Mockito(不需要從InvocationOnMock對象中獲取參數),並使測試的業務對象使用這個新的DAO。

此外,我讀過部分嘲諷被認爲是不好的做法。我的問題是:在我的情況下,我正在做一個不好的做法?有什麼缺點?對我來說這似乎很好,我想知道潛在的問題可能是什麼。

回答

1

在測試我的課程時,我經常使用Mockito製作的嘲笑和假贗品的組合,這些非常符合您的描述。在你的情況下,我同意虛假的實現聽起來更好。

部分模擬並沒有什麼特別的錯誤,但它使得確定何時調用真實對象以及何時調用模擬方法有點困難 - 尤其是因爲Mockito默默無聞地模擬最終方法。對原始類進行無辜修改可能會改變部分模擬的實現,導致測試停止工作。

如果您有靈活性,我建議您抽取一個接口,以顯示您需要調用的方法,這樣可以讓您更輕鬆地選擇模擬還是假。

要編寫一個假的,使用一個簡單的類(嵌套在你的測試中,如果你願意的話)實現那個沒有Mockito的小接口。這將使得很容易看到發生了什麼;缺點是如果你寫了一個非常複雜的僞裝,你可能會發現你也需要測試僞裝。如果你有很多測試可以使用一個好的僞造實現,這可能值得額外的代碼。

我強烈推薦"Mocks aren't Stubs",Martin Fowler的一篇文章(以他的着作重構而聞名)。他翻閱了不同類型的測試雙打的名字,以及他們之間的差異。

+0

謝謝。這對我來說是非常有用的建議:)我會在閱讀這篇文章之前先等待其他答案,然後再將其標記爲已接受的答案。 – machinery

2

我想知道爲什麼你需要你的假DAO支持HashMap。我想知道你的測試是否太複雜。我非常喜歡使用非常簡單的測試方法,每種方法都測試SUT行爲的一個方面。原則上,這是「每次測試的一個斷言」,儘管有時我最終得到一小部分實際的線,例如,如果我斷言複雜對象的正確性。請閱讀http://blog.astrumfutura.com/2009/02/unit-testing-one-test-one-assertion-why-it-works/http://blog.jayfields.com/2007/06/testing-one-assertion-per-test.html以瞭解有關此原理的更多信息。

因此,對於每種測試方法,您都不應該一遍又一遍地使用假的DAO。可能只是一次,或者最多兩次。因此,擁有大量的數據似乎對我來說是多餘的,或者說明你的測試做得比預想的要好得多。對於每種測試方法,您應該只需要一到兩個數據。如果您使用DAO界面的Mockito模擬來設置這些參數,並將您的when ... thenReturn本身放入測試方法中,那麼每個測試都將簡單易讀,因爲特定測試使用的數據將立即可見。

您可能還需要對「安排,法,斷言」模式,(http://www.arrangeactassert.com/why-and-what-is-arrange-act-assert/http://www.telerik.com/help/justmock/basic-usage-arrange-act-assert.html)念起來要小心有關實現此模式內的每個測試方法,而不是散落在測試的不同部分類。

沒有看到更多的實際測試代碼,很難知道其他建議給你。 Mockito應該讓嘲笑變得更輕鬆,而不是更難;所以如果你有一個測試不會發生在你身上,那麼肯定值得問你是否在做非標準的事情。你所做的不是「部分嘲諷」,但它對我來說似乎有點像一種測試氣味。尤其因爲它將很多測試方法結合在一起 - 問問自己如果必須更改HashMap中的某些數據會發生什麼情況。

您可能會發現https://softwareengineering.stackexchange.com/questions/158397/do-large-test-methods-indicate-a-code-smell也有用。