2

我正在尝试重构我的项目以提高可测试性,因此我正在引入一个抽象工厂。

我的应用程序使用ICrawlers. 这些ICrawlers 使用 3rd 方库来访问不同的来源,例如 twitter。

示例:我的 TwitterCrawler 使用TweetSharp访问 Twitter 数据。

我的第一个版本将 TweetSharp 客户端与 Crawler 强耦合。现在我将 TweetSharp 抽象为一个ITwitterClient和一个TweetSharpTwitterClient实现。

下一步是引入 aITwitterClientFactoryDefaultTwitterClientFactory创建TweetSharpTwitterClients。这应该使我更接近我的目标(可测试性),因为我可以将工厂切换到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?)的机制?

4

1 回答 1

3

不需要在单元测试中使用作曲家/容器- 只需将SUT直接与Test Doubles连接即可。

像这样的东西:

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

但是,您确实应该从属性注入重构为构造函数注入,因为该属性意味着依赖项是可选的。

顺便说一句,您的 DefaultTwitterClientFactory 不会自行导出,它会导出 ITwitterClient。

于 2011-05-03T09:57:48.530 回答