Mocking EF6 DbContext

  2015-06-02


If you are to write unit tests and at some point you might need to mock your DbContext (because we all know that unit tests should never connect to the actual database). In this blogpost I will walk through the details of mocking DbContext with EF6.

Step 1: install Coderful.EntityFramework.Testing

There’s quite a lot of boilerplate code involved in setting up DbContext mocking. To avoid writing the same code for each project I’ve put together this simple NuGet package. Just install it into your unit test project:

Install-Package Coderful.EntityFramework.Testing

If you’re interested in what’s going on inside of it, take a look at the source code.

Step 2: create MyMoqUtilities class

Now you’ll need to create a utility class, which will do the actual mocking of your DbContext.

First let’s assume that your DbContext has 2 DbSets:

public virtual DbSet<Contract> Contracts { get; set; }
public virtual DbSet<User> Users { get; set; }

Now to mock this DbContext you’d need to create a utility class like this one:

using System;
using System.Collections.Generic;
using Coderful.EntityFramework.Testing.Mock;
using Moq;

internal static class MyMoqUtilities
{
    public static MockedDbContext<MyDbContext> MockDbContext(
        IList<Contract> contracts = null,
        IList<User> users = null)
    {
        var mockContext = new Mock<MyDbContext>();

        // Create the DbSet objects.
        var dbSets = new object[]
        {
            mockContext.MockDbSet(contracts, (objects, contract) => contract.ContractId == (int)objects[0] && contract.AmendmentId == (int)objects[1]),
            mockContext.MockDbSet(users, (objects, user) => user.Id == (int)objects[0])
        };

        return new MockedDbContext<MyDbContext>(mockContext, dbSets); 
    }
}

Step 3: create and use the mocks

Now you’re all set and ready to create the mocks of your DbContext. The code is really simple:

// Create test data.
var contracts = new List<Contract>
{
    new Contract("#1"),
    new Contract("#2")
};

var users = new List<User>
{
    new User("John"),
    new User("Jane")
};

// Create DbContext with the predefined test data.
var dbContext = MyMoqUtilities.MockDbContext(
    contracts: contracts,
    users: users).DbContext.Object;

That’s it. Now you can use the dbContext object as if it was a standard DbContext instance:

// Add.
dbContext.Users.Add(newUser);

// Remove.
dbContext.Users.Remove(someUser);

// Query.
var john = dbContext.Users.Where(u => u.Name == "John");

// Save changes won't actually do anything, since all the data is kept in memory.
// This should be ideal for unit-testing purposes.
dbContext.SaveChanges();

Conclusion

I hope this helps. Please note that this technique is only possible with EF6 and onwards. Lastly leave the feedback in the comments!

22bugs.co © 2017. All rights reserved.