ChrisBint ChrisBint - 4 months ago 55
C# Question

Mocking DbContext in Entity Framework 6.1

I have found a number of examples that show (apparently) a clear working example of mocking DbContext with EF 6, however, none of them seem to work for me and I am not entirely sure why.

This is my unit test code that sets up the mock;

var mockData = new List<User> { new User { Email = "my@email.com", Id = 1 } }.AsQueryable();

var mockSet = new Mock<DbSet<User>>();
mockSet.As<IQueryable<User>>().Setup(m => m.Provider).Returns(mockData.Provider);
mockSet.As<IQueryable<User>>().Setup(m => m.Expression).Returns(mockData.Expression);
mockSet.As<IQueryable<User>>().Setup(m => m.ElementType).Returns(mockData.ElementType);
mockSet.As<IQueryable<User>>().Setup(m => m.GetEnumerator()).Returns(mockData.GetEnumerator());

var mockContext = new Mock<MyDbContext>();
mockContext.Setup(c => c.Users).Returns(mockSet.Object);


and then the call to the service I am testing;

var service = new UsersService(mockContext.Object);

var user = service.GetById(1);


This throws a NullReferenceException as the underlying DbSet is always null. The code does the following;

In BaseClass;

public IEnumerable<T> GetAll()
{
return _dbSet.AsEnumerable();
}


In subclass;

public User GetById(int id)
{
return GetAll().FirstOrDefault(x => x.Id == id);
}


Please note that although there are other questions on SO that appear to be related, they do not cover EF 6.

For reference, this is an MSDN article that the same code with a modification to make it compile.

https://msdn.microsoft.com/en-us/data/dn314429.aspx

EDIT:

Reducing the complexity of the UserService (its uses generics/interfaces), the code is now simply;

public User GetById(int id)
{
return _dbContext.Set<User>().FirstOrDefault(x => x.Id == id);
}


If I change this further to;

var dbSet = _dbContext.Set<User>();
return dbSet.FirstOrDefault(x => x.Id == id);


I can clearly see that dbSet is null.

Answer

I think you need to create a setup on the Set<User>() method to return your mock.