單元測試(二)-樁對象

在單元測試時,不免會碰到一些外部依賴,外部依賴是指在系統中代碼與其交互的對象,並且沒法對其作人爲控制,好比文件系統、線程、內存、時間、數據庫結果集等,這時可使用僞對象(fake)來替代外部依賴,樁對象(stub)即是其中之一數據庫

 

一 樁對象函數

a) 樁對象是對系統中現有依賴項的一個替代品,可人爲控制。經過使用樁對象,無需涉及依賴項,便可直接對代碼進行測試。使用樁對象能夠輕鬆地控制模擬依賴項的返回值會行爲(好比模擬內存溢出異常)。單元測試

b) 使用樁對象的前提是要找到原系統中的接縫(Seam)。接縫是指代碼中能夠插入不一樣功能(如樁對象類)的地方。有時須要經過重構來製造接縫並解除依賴的方法,能夠抽取接口來製造接縫,這樣底層實現就能夠被替換了。測試

 

 

二 替換底層實現的方法線程

 

經常使用的替換底層實現的方法有:對象

在構造函數中接收一個接口實現(構造函數注入)接口

在屬性中接收一個接口實現(屬性注入)內存

在方法的參數中接收一個接口實現(參數注入)it

使用工廠方法產生接口實現io

 

a) 在構造函數中接收一個接口實現

若是要使用類LogAnalyzer中的IsValidLogFileName方法來判斷文件名是否有效,在生產環境下,IsValidLogFileName方法要讀取配置文件,而後根據配置內容來進行判斷,這個方法依賴文件系統。重構過程以下:

抽取IExtensionManager

 

 

經過構造函數傳遞IExtensionManager的實現,判斷文件名是否有效交給IExtensionManager.IsValid來作

 

 

在測試代碼中,構造僞對象FakeExtensionManager並傳遞給LogAnalyzer

 

 

僞對象FakeExtensionManager是可控的

 

 

b) 屬性注入和參數注入與構造函數注入的實現方法是相似的,但經過構造函數或參數注入意味着參數是必須的,而屬性注入倒是可選的,因此使用屬性注入時要注意默認注入的處理。

 

c) 使用工廠產生接口實現

在工廠類中,Create()方法默認返回生產環境的FileExtensionManager,測試代碼能夠經過SetManager傳遞僞對象

 

 

LogAnalyzer經過Create方法取得IExtensionManager的接口實現

 

 

在測試代碼中,調用ExtensionManagerFactory.SetManager(**)注入FakeExtensionManager僞對象

 

 

d) 除了上述方法,還有不少方法能夠達到解除依賴的目的,好比基類、重寫等方式。但無論哪一種方法,爲了測試而重構可能會破壞一些面向對象的基本原則,好比封裝。這就須要努力在可測試性和封裝之間取得平衡,雖然這比較困難,但保證可測試性也是很重要的。

 

參考資料:

The Art of Unit Testing with examples in C#, 2nd Edition by Roy Osherove

相關文章
相關標籤/搜索