2015-06-19 61 views
1

我一直在做單元測試。在做TDD時,我對設計和實現細節之間的界限有點​​困惑。在做TDD時區分設計和實現細節

例如,我有兩個接口,服務和適配器,這個過程員工信息(添加,獲取,刪除...)

public interface IEmployeeService 
{ 
    Employee GetEmployeeById(int id) 
} 

public interface IEmployeeAdapter 
{ 
    private IEmployeeService _service 
    Employee GetEmployeeById(int id) 
} 

在設計,服務從存儲如數據庫,文件讀取數據系統或Web服務,適配器使用服務來獲取某些信息。

這個設計看起來很好,直到我開始爲適配器編寫單元測試。

問題是我需要知道adapter.GetEmployeeById(id)是否會調用service.GetEmployeeById(id)(或其他方法)來確定我是否需要在測試方法中模擬服務。這讓我覺得我在編寫單元測試時考慮了實現細節。有什麼不對的嗎?

回答

2

單元測試是white-box測試,因此您完全知道被測系統內部發生了什麼。使用這些信息來幫助確定模擬什麼是沒有問題的。是的,這是一個實現細節,當你的底層實現發生變化時,它可以使你的測試「脆弱」,從而需要改變它。但是在這種情況下,我想知道當我調用adapter.foo()時,它會調用underlyingService.foo(),而mock對此非常合適。

2

我可以建議的最佳經驗法則是:只有在它是合同的一部分的情況下才嘗試使用行爲設置/驗證。如果你測試行爲,但你實際上感興趣的是狀態,測試往往會更頻繁地破壞,因爲行爲實際上是一個實現細節。

在您的示例中,如果沒有人關心服務和適配器之間的確切邊界,請隨時在適配器類上使用狀態驗證。但是,如果您的適配器應該將特定的消息調用模式轉換爲另一組定義明確的消息,則可能需要使用行爲驗證。換句話說,如果adapter.GetEmployeeById(id)需要轉換爲service.GetEmployeeById(id)那麼它不是一個實現細節。