2011-05-03 127 views
2

我正在嘗試重構我的項目以提高可測試性,因此我介紹了一個抽象工廠。MEF和工廠模式

我的應用程序使用ICrawlers收集不同來源的數據。 這些ICrawler使用第三方庫來訪問不同的來源,例如,推特。

示例:我的TwitterCrawler使用TweetSharp訪問Twitter數據。

我的第一個版本強烈地將TweetSharp客戶端與Crawler結合在一起。現在我將TweetSharp抽象爲ITwitterClientTweetSharpTwitterClient實現。

下一步是引入ITwitterClientFactoryDefaultTwitterClientFactory創建TweetSharpTwitterClient s。這應該使我更接近我的目標(可測試性),因爲我可以將工廠切換到MockTwitterClientFactory,創建MockTwitterClient,它提供了一些測試輸出。

現在,讓我來談談我的觀點。 我正在使用MEF進行依賴注入(但我對它很陌生)。我在做什麼是這樣的:

public class TwitterCrawler : CrawlerBase, ICrawler 
{ 
    [Import] 
    public ITwitterClientFactory TwitterClientFactory {get; set;} 

    public override Process() 
    { 
     ITwitterClient twitterClient = TwitterClientFactory.MakeSingletonClient(); 
     // do something with twitterClient 
    } 
} 

而我DefaultTwitterClientFactory出口本身MEF:

[Export(typeof(ITwitterClient))] 
public class DefaultTwitterClientFactory: ITwitterClientFactory 
{ 
    // implementation of ITwitterClientFactory 
    // provides methods to create instances of ITwitterClient implementations 
} 

現在,雖然到目前爲止是這種情況,我的問題是,如何切換工廠? 如何創建單元測試並使用MockClientFactory而不是DefaultTwitterClientFactory

我的方法很好嗎?手動設置要使用的工廠是否更好? 某處像

... new TwitterCrawler(mockedTwitterClientFactory)

甚至

.... new TwitterCrawler(mockedTwitterClient)

這實際上只是將問題移出TwitterClient之外,但仍然需要決定如何構建ITwitterClient以及用於該目的的工廠。

我應該更深入進入MEF的機制(ExportProvider?)

回答

3

shouldn't need to use the composer/container in your unit tests - 剛剛與Test Doubles接線SUT直接。

事情是這樣的:

var sut = new TwitterCrawler(); 
sut.TwitterClientFactory = new FakeTwitterClientFactory(); 

但是,你真的應該從物業注射重構爲構造函數注入,與物業暗示的依賴是可選的。

順便說一句,您的DefaultTwitterClientFactory不會自行導出,它會導出ITwitterClient。

+0

感謝馬克。這對我來說真的很有意義。無論使用什麼DI,測試都應運行,因此將其從SUT中移除將重點放在要測試的設備上。我知道了! – Stefan 2011-05-03 13:10:55