在entity framework6.1中模拟DbContext

我发现了一些例子(显然)显示了用EF 6模拟DbContext的明显工作示例,然而,它们似乎都不适合我,我不完全确定原因。

这是我设置模拟的unit testing代码;

var mockData = new List { new User { Email = "my@email.com", Id = 1 } }.AsQueryable(); var mockSet = new Mock<DbSet>(); mockSet.As<IQueryable>().Setup(m => m.Provider).Returns(mockData.Provider); mockSet.As<IQueryable>().Setup(m => m.Expression).Returns(mockData.Expression); mockSet.As<IQueryable>().Setup(m => m.ElementType).Returns(mockData.ElementType); mockSet.As<IQueryable>().Setup(m => m.GetEnumerator()).Returns(mockData.GetEnumerator()); var mockContext = new Mock(); mockContext.Setup(c => c.Users).Returns(mockSet.Object); 

然后调用我正在测试的服务;

 var service = new UsersService(mockContext.Object); var user = service.GetById(1); 

这会抛出NullReferenceException,因为底层DbSet始终为null。 代码执行以下操作;

在BaseClass;

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

在子类中;

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

请注意,尽管SO上还有其他与之相关的问题,但它们不包括EF 6。

作为参考,这是一篇MSDN文章,相同的代码带有修改以使其编译。

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

编辑:

降低UserService(它使用generics/接口)的复杂性,现在代码简单;

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

如果我进一步改变这个;

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

我可以清楚地看到dbSet为null。

编辑2

根据wablab的建议,似乎mock .Set解决了这个问题。

同样感谢Vladyslav Kushnir的DbSet通用方法。

为可能需要它的任何人提供此代码的工作代码;

  private static Mock<DbSet> GetDbSetMock(IEnumerable items = null) where T : class { if (items == null) { items = new T[0]; } var dbSetMock = new Mock<DbSet>(); var q = dbSetMock.As<IQueryable>(); q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator); return dbSetMock; } var mockContext = new Mock(); var users = new List { new User { Email = "my@email.com", Id = 1 } }; mockContext.Setup(x => x.Set()).Returns(GetDbSetMock(users).Object); var service = new UsersService(mockContext.Object); var user = service.GetById(1); 

我想你需要在Set()方法上创建一个设置来返回你的mock。

  private Mock> GetDbSetMock(IEnumerable items = null) where T : class { if (items == null) { items = new T[0]; } var dbSetMock = new Mock>(); var q = dbSetMock.As>(); q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator); return dbSetMock; } 

这是我用来模拟DbContext的DbSet的非常好的通用方法。 这种方法的实际调用是:

 var contextMock = new Mock(); contextMock.Setup(x => x.MyDbEntities).Returns(GetDbSetMock().Object);