如何使用Entity Framework和Moq进行unit testing?

我是Moq的新手,想要像数据的后备存储一样使用它 – 但是没有触及实时数据库。

我的设置如下:

  • UnitOfWork包含所有存储库,用于整个应用程序的数据访问。
  • Repository表示由DbContext提供的直接挂钩到DbSet。
  • DbContext包含所有DbSet。

这是我到目前为止的测试:

// ARRANGE var user = new User() { FirstName = "Some", LastName = "Guy", EmailAddress = "some.guy@mockymoqmoq.com", }; var mockSet = new MockDbSet(); var mockContext = new Mock(); mockContext.Setup(c => c.Set()).Returns(mockSet.Object); // ACT using (var uow = UnitOfWork.Create(mockContext.Object)) { uow.UserRepository.Add(user); uow.SaveChanges(); } // ASSERT mockSet.Verify(u => u.Add(It.IsAny()), Times.Once()); 

我的测试似乎是成功的,因为它可以validation用户是否已添加到模拟DbSet中 – 但我需要做的是实际获取该数据并对其执行进一步的断言(这只是一个临时测试)。

请指教,测试框架正在努力。另外,如果它们更容易使用,我可以选择转移到其他测试框架。

谢谢。

更新:这是我的工作代码。

unit testing

  // ARRANGE var user = new User() { FirstName = "Some", LastName = "Guy", EmailAddress = "some.guy@mockymoqmoq.com", }; var mockSet = new MockDbSet(); var mockContext = new Mock(); mockContext.Setup(c => c.Set()).Returns(mockSet.Object); // ACT using (var uow = UnitOfWork.Create(mockContext.Object)) { uow.UserRepository.Add(user); uow.SaveChanges(); } // ASSERT mockSet.Verify(u => u.Add(It.IsAny()), Times.Once()); // TODO: Further assertations can now take place by accessing mockSet.BackingStore. } 

MockDbSet

 class MockDbSet : Mock<DbSet> where TEntity : class { public ICollection BackingStore { get; set; } public MockDbSet() { var queryable = (this.BackingStore ?? (this.BackingStore = new List())).AsQueryable(); this.As<IQueryable>().Setup(e => e.Provider).Returns(queryable.Provider); this.As<IQueryable>().Setup(e => e.Expression).Returns(queryable.Expression); this.As<IQueryable>().Setup(e => e.ElementType).Returns(queryable.ElementType); this.As<IQueryable>().Setup(e => e.GetEnumerator()).Returns(() => queryable.GetEnumerator()); // Mock the insertion of entities this.Setup(e => e.Add(It.IsAny())).Returns((TEntity entity) => { this.BackingStore.Add(entity); return entity; }); // TODO: Other DbSet members can be mocked, such as Remove(). } } 

您只需创建一个集合作为后备存储,并使用后备集合模拟枚举数据库集

 public class MockDbSet : Mock> where TEntity : class { public MockDbSet(List dataSource = null) { var data = (dataSource ?? new List()); var queryable = data.AsQueryable(); this.As>().Setup(e => e.Provider).Returns(queryable.Provider); this.As>().Setup(e => e.Expression).Returns(queryable.Expression); this.As>().Setup(e => e.ElementType).Returns(queryable.ElementType); this.As>().Setup(e => e.GetEnumerator()).Returns(() => queryable.GetEnumerator()); //Mocking the insertion of entities this.Setup(_ => _.Add(It.IsAny())).Returns((TEntity arg) => { data.Add(arg); return arg; }); //...the same can be done for other members like Remove } } 

所以现在您可以使用列表来保存数据

 // ARRANGE var dataSource = new List(); //<-- this will hold data var user = new User() { FirstName = "Some", LastName = "Guy", EmailAddress = "some.guy@mockymoqmoq.com", }; var mockSet = new MockDbSet(dataSource); var mockContext = new Mock(); mockContext.Setup(c => c.Set()).Returns(mockSet.Object); // ACT using (var uow = UnitOfWork.Create(mockContext.Object)) { uow.UserRepository.Add(user); uow.SaveChanges(); // ASSERT mockSet.Verify(u => u.Add(It.IsAny()), Times.Once()); Assert.IsTrue(dataSource.Contains(user)); //<-- shows mock actually added item Assert.IsTrue(uow.UserRepository.Any(u => u == user)); //<-- show you can actually query mock DbSet }