在單元測試時,難免會碰到一些外部依賴,外部依賴是指在系統中**與其互動的物件,而且無法對其做人為控制,比如檔案系統、執行緒、記憶體、時間、資料庫結果集等,這時可以使用偽物件(fake)來替代外部依賴,樁物件(stub)便是其中之一
一 樁物件
a) 樁物件是對系統中現有依賴項的乙個替代品,可人為控制。通過使用樁物件,無需涉及依賴項,即可直接對**進行測試。使用樁物件可以輕鬆地控制模擬依賴項的返回值會行為(比如模擬記憶體溢位異常)。
b) 使用樁物件的前提是要找到原系統中的接縫(seam)。接縫是指**中可以插入不同功能(如樁物件類)的地方。有時需要通過重構來製造接縫並解除依賴的方法,可以抽取介面來製造接縫,這樣底層實現就可以被替換了。
二 替換底層實現的方法
常用的替換底層實現的方法有:
在建構函式中接收乙個介面實現(建構函式注入)
在屬性中接收乙個介面實現(屬性注入)
在方法的引數中接收乙個介面實現(引數注入)
使用工廠方法產生介面實現
a) 在建構函式中接收乙個介面實現
如果要使用類loganalyzer中的isvalidlogfilename方法來判斷檔名是否有效,在生產環境下,isvalidlogfilename方法要讀取配置檔案,然後根據配置內容來進行判斷,這個方法依賴檔案系統。重構過程如下:
抽取iextensionmanager
通過建構函式傳遞iextensionmanager的實現,判斷檔名是否有效交給iextensionmanager.isvalid來做
在測試**中,構造偽物件fakeextensionmanager並傳遞給loganalyzer
偽物件fakeextensionmanager是可控的
b) 屬性注入和引數注入與建構函式注入的實現方法是類似的,但通過建構函式或引數注入意味著引數是必須的,而屬性注入卻是可選的,所以使用屬性注入時要注意預設注入的處理。
c) 使用工廠產生介面實現
在工廠類中,create()方法預設返回生產環境的fileextensionmanager,測試**可以通過setmanager傳遞偽物件
loganalyzer通過create方法取得iextensionmanager的介面實現
在測試**中,呼叫extensionmanage***ctory.setmanager(**)注入fakeextensionmanager偽物件
d) 除了上述方法,還有很多方法可以達到解除依賴的目的,比如基類、重寫等方式。但不管哪種方法,為了測試而重構可能會破壞一些物件導向的基本原則,比如封裝。這就需要努力在可測試性和封裝之間取得平衡,雖然這比較困難,但保證可測試性也是很重要的。
單元測試 二 樁物件
在單元測試時,難免會碰到一些外部依賴,外部依賴是指在系統中 與其互動的物件,而且無法對其做人為控制,比如檔案系統 執行緒 記憶體 時間 資料庫結果集等,這時可以使用偽物件 fake 來替代外部依賴,樁物件 stub 便是其中之一 一 樁物件 a 樁物件是對系統中現有依賴項的乙個替代品,可人為控制。通...
單元測試關於樁函式的探索
背景 c語言編寫的目標檔案,在做單元測試的時候,在目標c檔案 如target.c 中想測試乙個函式a,而a呼叫了b,b目前無法實現,所以需要打樁來代替b.在不改變target.c的前提下 不修改程式的 在另外的c檔案中 test.c 寫樁函式,怎樣讓a函式執行的時候呼叫樁函式,而不是原來的b函式呢?...
談談單元測試中的測試樁實踐 2
首先定義乙個clock 介面。並為clock 顧名思義其實就是實現了clock 的ntpclock 另乙個是systemclock 它就提供系統當前時間作為標準時間。packageshannon.demo clock isan inte ce forall theclock toprovide ti...