问题描述
我发现了一些例子,显示(显然)一个清晰的工作示例,用EF 6模拟DbContext,但是,他们似乎都没有为我工作,我不完全确定为什么。
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 = "[email protected]", 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);
这将抛出一个NullReferenceException,因为底层的DbSet始终为空。代码执行以下操作:
This throws a NullReferenceException as the underlying DbSet is always null. The code does the following;
在BaseClass中;
In BaseClass;
public IEnumerable<T> GetAll()
{
return _dbSet.AsEnumerable();
}
在子类中
public User GetById(int id)
{
return GetAll().FirstOrDefault(x => x.Id == id);
}
请注意,尽管SO上还有其他与此相关的问题,它们不覆盖EF 6。
Please note that although there are other questions on SO that appear to be related, they do not cover EF 6.
为了参考,这是一个MSDN文章,具有修改的相同代码进行编译。
For reference, this is an MSDN article that the same code with a modification to make it compile.
编辑:
降低UserService的复杂性它使用泛型/接口),代码现在简单;
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);
我可以清楚地看到dbSet为空。
I can clearly see that dbSet is null.
编辑2
根据wablab的建议,似乎mock.Set解决了这个问题。
As per the suggestion from wablab, it appears that mock .Set resolved the problem.
还要给Vladislav Kushnir的DbSet的通用方法。
Credit also to Vladyslav Kushnir for the Generic method for DbSet.
为任何可能需要它的人的工作代码;
Working code for this for anyone that might need it;
private static Mock<DbSet<T>> GetDbSetMock<T>(IEnumerable<T> items = null) where T : class
{
if (items == null)
{
items = new T[0];
}
var dbSetMock = new Mock<DbSet<T>>();
var q = dbSetMock.As<IQueryable<T>>();
q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator);
return dbSetMock;
}
var mockContext = new Mock<Model1>();
var users = new List<User> { new User { Email = "[email protected]", Id = 1 } };
mockContext.Setup(x => x.Set<User>()).Returns(GetDbSetMock(users).Object);
var service = new UsersService(mockContext.Object);
var user = service.GetById(1);
推荐答案
我想您需要在设置< User>()
方法返回您的模拟。
I think you need to create a setup on the Set<User>()
method to return your mock.
这篇关于在实体框架中模拟DbContext 6.1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!