EF6 DbSet <T> returns null in Moq
I have a typical repository template setup in my application with DbContext (EF6):
public class MyDbContext : EFContext<MyDbContext> { public MyDbContext () { } public virtual DbSet<CartItem> Cart { get; set; } and repository:
public class GenericEFRepository<TEntity, TContext> where TEntity : class, new() where TContext : EFContext<TContext> { private readonly TContext _context; public GenericEFRepository(TContext context) { _context = context; } //... public virtual TEntity Insert(TEntity item) { return _context.Set<TEntity>().Add(item); } I am testing this with Moq 4.2 (following this tutorial ), creating a context layout:
// Arrange var mockSet = new Mock<DbSet<CartItem>>(); var mockContext = new Mock<MyDbContext>(); mockContext.Setup(c => c.Cart).Returns(mockSet.Object); // Act var service = new GenericEFRepository<CartItem, MyDbContext>(mockContext.Object); service.Insert(new CartItem() { Id = 1, Date = DateTime.Now, UserId = 1, Detail = string.Empty }); // Assert mockSet.Verify(s => s.Add(It.IsAny<CartItem>()), Times.Once()); The problem is that when I reach this line:
return _context.Set<TEntity>().Add(item); _context.Set<TEntity>() returns null. After some searching in EF5, it was necessary to return an IDbSet<T> for Moq in order to mock the set, but not with EF6. Is this not true, or am I missing something?
Add a setting for the Set<T>() method:
mockContext.Setup(c => c.Set<CartItem>()).Returns(mockSet.Object); Even if the Cart and Set<CartItem>() property refer to the same object on the real EFContext , the context layout does not know this, so you need to explicitly tell it what to return.
Since it was a free layout, calling a method that was not configured returns a default value, which in this case is null . Severe bullying helps to find this error, but also has maintenance costs that other people do not want to deal with .