Mocking EF DbContext with Moq
c#, dbcontext, entity-framework-5, moq, unit-testing
Solution
I managed to solve it by creating a `FakeDbSet<T>` class that implements `IDbSet<T>`
public class FakeDbSet<T> : IDbSet<T> where T : class
{
ObservableCollection<T> _data;
IQueryable _query;
public FakeDbSet()
{
_data = new ObservableCollection<T>();
_query = _data.AsQueryable();
}
public virtual T Find(params object[] keyValues)
{
throw new NotImplementedException("Derive from FakeDbSet<T> and override Find");
}
public T Add(T item)
{
_data.Add(item);
return item;
}
public T Remove(T item)
{
_data.Remove(item);
return item;
}
public T Attach(T item)
{
_data.Add(item);
return item;
}
public T Detach(T item)
{
_data.Remove(item);
return item;
}
public T Create()
{
return Activator.CreateInstance<T>();
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
{
return Activator.CreateInstance<TDerivedEntity>();
}
public ObservableCollection<T> Local
{
get { return _data; }
}
Type IQueryable.ElementType
{
get { return _query.ElementType; }
}
System.Linq.Expressions.Expression IQueryable.Expression
{
get { return _query.Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return _query.Provider; }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _data.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _data.GetEnumerator();
}
}
Now my test looks like this:
[TestMethod]
public void TestGetAllUsers()
{
//Arrange
var mock = new Mock<IDbContext>();
mock.Setup(x => x.Set<User>())
.Returns(new FakeDbSet<User>
{
new User { ID = 1 }
});
UserService userService = new UserService(mock.Object);
// Act
var allUsers = userService.GetAllUsers();
// Assert
Assert.AreEqual(1, allUsers.Count());
}
Problem
I'm trying to create a unit test for my service with a mocked DbContext. I created an interface `IDbContext` with the following functions: ``` public interface IDbContext : IDisposable { IDbSet<T> Set<T>() where T : class; DbEntityEntry<T> Entry<T>(T entity) where T : class; int SaveChanges(); } ``` My real context implements this interface `IDbContext` and `DbContext`. Now I'm trying to mock the `IDbSet<T>` in the context, so it returns a `List<User>` instead. ``` [TestMethod] public void TestGetAllUsers() { // Arrange var mock = new Mock<IDbContext>(); mock.Setup(x => x.Set<User>()) .Returns(new List<User> { new User { ID = 1 } }); UserService userService = new UserService(mock.Object); // Act var allUsers = userService.GetAllUsers(); // Assert Assert.AreEqual(1, allUsers.Count()); } ``` I always get this error on `.Returns`: ``` The best overloaded method match for 'Moq.Language.IReturns<AuthAPI.Repositories.IDbContext,System.Data.Entity.IDbSet<AuthAPI.Models.Entities.User>>.Returns(System.Func<System.Data.Entity.IDbSet<AuthAPI.Models.Entities.User>>)' has some invalid arguments ```