2011-06-08 61 views
2

我有一個讀取pop3電子郵件服務器的類。我想爲包含類編寫一些單元測試,所以我需要模擬POP3服務器類。我正在使用OpenPOP.Net。所以我有這樣一個構造函數:關於模擬框架C#和單元測試的問題

EmailHost(string email, string password, string pop3Address, int port) 
... etc.... 

再後來我有一個連接類:

private void Connect() 
{ 
    _pop3 = new Pop3Client(); 
    etc... 

所以參考POP客戶端埋在類的膽量。爲了能夠嘲笑它,我需要做一些時髦的東西,因爲作爲製作EmailHost通用的Pop3Client,或添加一些功能,用默認做上述行:

public EmailHost<PopClass>(...) 

public EmailHost(... params, Func popGenerate =() => new Pop3Client()) 

所以看來我必須妥協一下我的構造函數才能使它與模擬一起工作。 (顯然我會定義一個IPop3Client等)。

有關如何正確執行此操作的任何想法?

編輯:

JOK提供了一個有趣的答案,問題是,它沒有的我在做什麼結構內吻合。在這種特殊情況下,我需要處理Pop客戶端中的多個電子郵件地址,並動態添加。因此,當您添加每個電子郵件地址時,您需要創建一個新的Pop3Client。另外,我想隱藏POP3本身的實現,以便用戶不需要儘可能多地瞭解它。

還有其他想法嗎?

感謝您輸入btw。

+0

您是否在項目中使用Spring? – 2011-06-08 19:03:30

回答

4

我覺得你很接近。

而不是傳入所有最終將用於創建Pop3Client實例的參數,請考慮注入一個Pop3Client實例。

public EmailHost(IPop3Client client) { 

} 

通過這樣做,你從創建Pop3Client對象的責任刪除您EmailHost類。這個責任轉移到別的地方,最常見的是轉移到一個IoC容器。

我無法從您發佈的代碼中判斷Pop3Client是否基於接口。如果是,很好,你可以在你的測試中模擬/存根並注入依賴。如果沒有,那麼在操作它時會涉及更多的工作,以便在這種情況下工作。它可以像在類中公開你在EmailHost中使用的方法一樣簡單地寫一個包裝器(和相應的接口)。這可以在上面的例子中用來代替IPop3Client。

這有道理嗎?讓我知道你是否需要更多指導。

+0

+1好的答案 - 正如你所說的,使依賴注入是關鍵,不管這是否通過IOC容器完成是一個單獨的考慮因素 - 人們經常認爲DI和IOC容器的使用是隱式鏈接的 – 2011-06-08 19:17:49

+0

@Adam Ralph同意。謝謝你強調這一點。 – csano 2011-06-08 19:19:48

+0

感謝您的信息。我編輯了原文,以反映爲什麼我不認爲這會起作用。 – 2011-06-08 19:41:01

0

使用像溫莎城堡這樣的服務地點。如果您不想更改構造函數,請在容器上調用Resolve,但這不是正確的方式。把依賴關係放在構造函數中是很好的建議。