Mocking a LINQ Queryable Repository for TDD

Using ORM frameworks like Entity Framework and NHibernate has become standard practice for many developers. POCO using Entity Framework also supports test-driven-development nicely since we can create tests for our business domain objects without having a dependency on the repository used to store them. Entity Framework also supports LINQ queries which allows us to avoid defining every conceivable query necessary for our application ahead of time, instead letting the code that uses the domain objects construct a query without even understanding the underlying physical database structure, including supporting queries that traverse multiple relationships in the model.

In theory defining an interface for the repository will also allow us to easily mock the repository implementation so that we can write tests using all aspects of our application without having to set up a physical database for our unit tests – which we really don’t want to do early on in development. Obviously any application that uses a database will also require non-mocked tests which verify that the database and the ORM framework are set up correctly and support the queries that are required! But while we are working on defining and testing our model or more important business logic we don’t want to have a dependency to an as yet to be defined database structure.

Setting Up

Unfortunately trying to mock a query enabled repository interface can lead to some interesting problems. I want to create a repository which will allow more or less any query to be executed. There is a standard interface for this: IQueryable. So my generic queryable repository will have an interface that resembles this.

public interface IMyQueryableRepository
{
  IQueryable<DomainObject> DomainObjects {get;}
  void Add(DomainObject item);
  void SaveChanges();
}

I want to be able to test this without creating a concrete repository and database.

//Test code
IMyQueryableRepository repositoryUnderTest = ...  SomeInitializer ...;
var itemToAdd = new DomainObject(){... initialize it ...};

//this would probably be something happening behind the scenes in our Code Under Test, inside an MVC controller for instance.
repositoryUnderTest.Add(itemToAdd);
repositoryUnderTest.SaveChanges();
//now I should be able to query using LINQ for example to count...
var count = repositoryUnderTest.DomainObjects(d => d.SomeProperty == SomeValue);

//once we have come out of our Code Under Tests
...Assert something of value like that the count had expected value...

Mocking Extension Methods is Tough

To be able to test this without implementing it requires a Mock, stub or fake. I love the Moq framework and use it whenever I can for testing dependencies. Using Moq I can easily create a mock object which has the desired behaviour for my backend and can simulate any logic I require. But using Moq the natural syntax would be the following.

var theMock = new Moq.Mock<IMyQueryableRepository>();
theMock.Setup(repo => repo.DomainObjects.Count(do => do.SomeProperty == SomeValue)).Returns(fakeCount);

Unfortunately this won’t work because the LINQ extension methods are not part of my repository and the code will throw an exception:

Expression references a method that does not belong to the mocked object

Using LINQ to Mock LINQ

So how can we use the repository without creating an implementation? We fall back to using LINQ and letting existing framework objects which understand and support LINQ do all the heavy lifting inside or mock implementation. We don’t really care about how the repository works internally we have som expectations on what exists inside the store for the repository. A much easier way to accomplish this is to return an object that supports the IQueryable interface using our mock.

List<DomainObject> db = new List<DomainObject>();
theMock.SetupGet(repo => repo.DomainObjects).Returns(db.AsQueryable());

Returning the list AsQueryable allows us to simply populate the list (db above) with whatever objects we would like to fake inside our database. This is also possible with Microsofts new Fakes feature in VS2012 the syntax is just slightly different.

var fakedRepo = new NameSpace.Fakes.StubIMyQueryableRepository();
fakedRepo.DomainObjectsGet = () => db.AsQueryable();

One of the creators of Moq Daniel Clazzulino (kzu) has several articles on how you can design a more complex Entity Framework repository for testing and tips on how to mock and test your own extension methods.

Leave A Comment...

*