wcfunit-testingmvvmwcf-clienttestability

How do you inject wcf client dependencies in a ViewModel and keep it testable?


TL;DR: What is a good and testable way to implement the dependency between the ViewModels and the WCF services in a MVVM client?

Please read the rest of the question for more details about the problems I encountered while trying to do this:


I am working on a silverlight client that connects to a wcf service, and I want to write unit tests for the client. So I'm looking for a good solution for using the wcf clients in my ViewModels and testing that interaction. I have found two solutions until now:

Solution 1: This is actually how I have implemented it until now:

public class ViewModelExample
{
    public ViewModelExample(IServiceClient client)
    {    
            client.DoWorkCompleted += .. 
            client.DoWorkAsync();
    }
}

//This is how the interface looks like
public interface IServiceClient
{
    event EventHandler<AsyncCompletedEventArgs> DoWorkCompleted;
    void DoWorkAsync();
}

//I was able to put the interface on the generated clients because they are partial classes, like this:
public partial class GeneratedServiceClient : IServiceClient
{

}

The good part: it's relatively easy to mock

The bad part: my service client lives as long as my ViewModel, and when I have concurrent requests I don't know which answer belongs to which request.

Solution 2: Inspired by this answer WCF Service Client Lifetime.

public class ViewModelExample
{
    public ViewModelExample(IServiceFactory factory)
    {
        var client = factory.CreateClient();
        client.DoWorkCompleted += ...
        client.DoWorkAsync();
    }
}

The good part: each request is on a different client, so no more problems with matching requests with answers.

The bad part: it's more difficult to test. I would have to write mocks for both the factory and the wcf client every time. This is not something I would like to do, since I alreay have 200 tests... :(

So my question is, how do you guys do it? How do your ViewModels talk to the wcf services, where do you inject the dependency, and how do you test that interaction? I feel that I'm missing something..


Solution

  • Try having a Func<IServiceClient> injected into your VM instead of the a client instance; you'll have a 'language-level factory' injected instead of building a class for this. In the factory method you can instantiate your client however you want (each access could create a new instance for that for example).

    The downside is that you'll still have to touch your tests for the most part, but I assume it will be less work:

    public ViewModelExample(Func<IServiceClient> factoryMethod)
    {
        var client = factoryMethod();
        client.DoWorkCompleted += ...
        client.DoWorkAsync();
    }