Question

I've inherited a WPF MVVM application which has virtually no unit tests. When I tried to write my own, I quickly realised why: the code hasn't been written in a manner that makes it easy to test, with a lot of concrete implementations.

A particular bugbear is the repository. There's an EF context underneath which I can't/don't want to test but I'm struggling to even get the thing to accept Mocks of the EF objects instead.

I'll hold my hand up and say: I'm not a very good architect. Can you help me untangle this a bit, and prod me toward where interfaces and such need to be added?

Here's a sample ViewModel from the application:

public class MyViewModel : BaseViewModel
{
    public MyViewModel(MyEFObject mEfObj)
    {
       //do stuff
    }

    // properties, methods etc etc
}

They all inherit from BaseViewModel:

public abstract class BaseViewModel : INotifyPropertyChanged
{
    private static MyRepository _rep;

    protected static MyRepository rep
    {
        get
        {
            if (_rep == null)
                _rep = new MyRepository();
            return _rep;
        }
    }

    // properties, methods etc etc
}

And so to the repository class:

public class MyRepository
{
    private MyEntitiesT db = new MyEntitiesT();

    //methods and properties that interact with the DB
}

And finally, at the bottom of the heap, that slightly peculiar entity wrapper:

public class MyEntitiesT : MyEntities
{
    public MyEntitiesT()
    {
        var objectContext = (this as IObjectContextAdapter).ObjectContext;
        objectContext.CommandTimeout = 0;
    }
}

So, I guess I really need an IMyRepositoryInterface over MyRepository, which would allow me to Mock that. But if I'm instantiating a MyViewModel object, how do I get in my mocked repository, since it's specified in BaseViewModel? Do I need to start fiddling with dependency injection?

Poor testability aside, this is a pretty functional application that I don't want to mess with excessively for fear of breaking it. So if there's a way I can get these things decoupled without making major structural changes, or at least by making them piecemeal (i.e. one ViewModel at a atime) it'd be useful.

Was it helpful?

Solution

You are right. You need IRepository and an implementation containing all the EF code like EfRepository.

I also saw that you are passing and EF Object to a ViewModel...

MyEFObject mEfObj

usually you just want to retrieve POCO's from your Repositories and pass in the Repository to the view model.

So start piece by piece. Take your existing repository and define an interface for it and implement it in the repository. And start to exchange the concrete class definition in the constructor with the interface... and then work from there how deep you need and want to go... And start adding tests on your way... they will build up soon...

Before you use Dependency injection framework start with something like this...

  private readonly IRepository _repository;
   public MyViewModel() : this(new EfRepository())
   {
   }
   public MyViewModel(IRepository repository)
   {
      _repository = repository;
   }

This should only be an intermediate step but helps you to refactor to implement a contract based on interfaces. After that look for DI and ViewModelLocator pattern

To go with constructor injection and Interfaces is a good step because they are easy mockable and you can also use mocking frameworks to provide expected behavior from within your unit test.

HTH

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top