【问题标题】:MEF and Factory PatternMEF 和工厂模式
【发布时间】:2023-04-08 18:11:02
【问题描述】:

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

我的应用程序使用ICrawlers 从不同来源收集数据。 这些ICrawlers 使用 3rd 方库来访问不同的源,例如推特。

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

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

下一步是引入ITwitterClientFactoryDefaultTwitterClientFactory,从而创建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)的机制吗?

【问题讨论】:

    标签: c#-4.0 dependency-injection mef factory-pattern testability


    【解决方案1】:

    shouldn't need to use the composer/container in your unit tests - 只需将 SUT 直接与 Test Doubles 连接即可。

    类似这样的:

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

    然而,你真的应该从属性注入重构为构造函数注入,因为属性意味着依赖是可选的。

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

    【讨论】:

    • 谢谢马克。这对我来说真的很有意义。无论使用什么 DI,测试都应该运行,因此将其从 SUT 中删除是专注于要测试的单元。我明白了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多