开发者

MEF and Factory Pattern

i am trying to refactor my project to improve testability, therefor i'm introducing an abstract factory.

My application collects data from different sources by using ICrawlers. These ICrawlers use 3rd party libraries to access different sources, like e.g. twitter.

Example: My TwitterCrawler uses TweetSharp to access twitter data.

My first version strongly coupled the TweetSharp client to the Crawler. Now i abstracted the TweetSharp to a ITwitterClient and a TweetSharpTwitterClient implementation.

Next step is to introduce a ITwitterClientFactory with a DefaultTwitterClientFactory that creates TweetSharpTwitterClients. This should bring me closer to my goal (testability) because i can switch the factory to MockTwitterClientFactory that creates a MockTwitterClient, that delivers some test output.

Now, let me come to my point. I am using MEF for dependency injection (but i'm rather new to it). What I'm doing is this:

public class TwitterCrawler : CrawlerBase, ICrawler 
{
    [Import]
    public ITwitterC开发者_开发知识库lientFactory TwitterClientFactory {get; set;}

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

Whereas my DefaultTwitterClientFactory exports itself to MEF:

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

Now, while this works so far, my question is, how to switch the factory? How can i create a unit test and use the MockClientFactory instead of the DefaultTwitterClientFactory?

Is my approach good at all? Is it better to manually set the factory that is to be used? Somewhere something like

... new TwitterCrawler(mockedTwitterClientFactory)

or even

.... new TwitterCrawler(mockedTwitterClient)?

This actually only moves the problem outside of TwitterClient, but still somewhere i have to decide how to construct the ITwitterClient and what factory to use for that purpose.

Should i dive more into the mechanics of MEF (ExportProvider?)


You shouldn't need to use the composer/container in your unit tests - just wire the SUT directly with the Test Doubles.

Something like this:

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

However, you should really refactor from Property Injection to Constructor Injection, as the property implies that the dependency is optional.

BTW, your DefaultTwitterClientFactory doesn't export itself, it exports ITwitterClient.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜