2011-03-07 78 views
4

我在問關於模擬對象管理,無論具體實現(EasyMock,Mock Object等)。如何保持Mock對象與目標對象同步

我一直不願意在我的單元測試中使用Mock對象,原因如下: Mock對象的行爲必須鏡像被模擬對象的行爲。如果被模擬對象的行爲發生了變化,我們也必須改變模擬對象的行爲。如果我們不這樣做,模擬對象的行爲將與實際對象不同步,從而使單元測試變得毫無意義,而且這是危險的。

我的問題是, 如何保持模擬對象與目標對象同步? 你如何傳播變化? 您是否使用任何模擬對象管理技術?

編輯: 更改標題以縮小範圍。

回答

2

定義良好的API不應該有這樣的餘地:給定一組輸入,被模擬的對象應該只能以這些特定的方式運行:行爲與接口綁定。如果允許有差異,那麼你的模擬對象應該測試這個對象可以做的所有不同的事情。

可以減輕行爲漂移的風險:

  • 集成測試,並
  • 與實際執行的比較數據嘲笑。
0

你在正確的軌道上。您不需要每次重構被測系統時都必須更改的脆弱測試。

一般來說,我將測試集中在公共接口上。如果你的公共接口改變了,你可能不得不改變測試。

我也嘗試做狀態測試,而不是行爲測試,只要有可能。所以我通常會使用stubs instead of mocks。 (大多數隔離/模擬框架可以讓你創建。)我驗證被測系統(或類)的狀態,而不是讓一個模擬對象來驗證自己。

這就是說,我儘量保持靈活。如果在特定情況下測試模擬行爲是有意義的,我會使用它。如果我需要揭露內部機構以獲得體面的覆蓋面,我會的。

編輯:另請參閱此article by Scott Bain

0

我不是專家,但我的想法是,模擬對象是爲單個測試用例/交互設計的。如果這種互動發生變化,您顯然希望這些反映在您的測試中。但是,當它們檢查可能仍然有效的不同交互時,這不應該破壞類的所有模擬對象。

0

如果ClassA的來電:

AThing aThing = ClassB.GiveMeAThing() 

ClassA的不應該關心ClassB的如何得到那個東西。因此,一個存根StubB永遠不應該關心存根的真正實現如何表現。只有當交互本身改變 - 返回類型或調用參數 - StubB應該被改變,並且如果你想讓你的代碼編譯,那將需要:-)

如果你的ClassB開始返回Nulls或Throws新類型的異常;那麼,那麼就會有全新的測試被寫入,並且可能還有新的存根。

Regards, Morten