How do I go about unit testing with Entity Framework and Moq?(如何使用 Entity Framework 和 Moq 进行单元测试?)
问题描述
我是 Moq 的新手,想将它用作数据的后备存储 - 但不接触实时数据库.
I'm new to Moq, and wanting to use it like a backing store for data - but without touching the live database.
我的设置如下:
- UnitOfWork 包含所有存储库,用于在整个应用程序中访问数据.
- Repository 表示 DbSet 的直接挂钩,由 DbContext 提供.
- 一个 DbContext 包含所有 DbSet.
这是我目前的测试:
// ARRANGE
var user = new User()
{
FirstName = "Some",
LastName = "Guy",
EmailAddress = "some.guy@mockymoqmoq.com",
};
var mockSet = new MockDbSet<User>();
var mockContext = new Mock<WebAPIDbContext>();
mockContext.Setup(c => c.Set<User>()).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<User>()), Times.Once());
我的测试似乎成功了,因为它可以验证用户是否已添加到模拟 DbSet - 但我需要做的实际上是取回该数据并对其执行进一步的断言(这只是一个临时测试).
My test seems to be successful, as it can verify that a user was added to the mock DbSet - but what I need to do is actually get that data back and perform further assertions on it (this is just an ad-hoc test).
请告知,测试框架正在我的头上.另外,如果它们更易于使用,我可以选择迁移到其他测试框架.
Please advise, testing frameworks are doing my head in. Also, I have the option to move to other testing frameworks if they are easier to use.
谢谢.
更新:这是我的工作代码.
单元测试
// ARRANGE
var user = new User()
{
FirstName = "Some",
LastName = "Guy",
EmailAddress = "some.guy@mockymoqmoq.com",
};
var mockSet = new MockDbSet<User>();
var mockContext = new Mock<WebAPIDbContext>();
mockContext.Setup(c => c.Set<User>()).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<User>()), Times.Once());
// TODO: Further assertations can now take place by accessing mockSet.BackingStore.
}
MockDbSet
class MockDbSet<TEntity> : Mock<DbSet<TEntity>> where TEntity : class
{
public ICollection<TEntity> BackingStore { get; set; }
public MockDbSet()
{
var queryable = (this.BackingStore ?? (this.BackingStore = new List<TEntity>())).AsQueryable();
this.As<IQueryable<TEntity>>().Setup(e => e.Provider).Returns(queryable.Provider);
this.As<IQueryable<TEntity>>().Setup(e => e.Expression).Returns(queryable.Expression);
this.As<IQueryable<TEntity>>().Setup(e => e.ElementType).Returns(queryable.ElementType);
this.As<IQueryable<TEntity>>().Setup(e => e.GetEnumerator()).Returns(() => queryable.GetEnumerator());
// Mock the insertion of entities
this.Setup(e => e.Add(It.IsAny<TEntity>())).Returns((TEntity entity) =>
{
this.BackingStore.Add(entity);
return entity;
});
// TODO: Other DbSet members can be mocked, such as Remove().
}
}
推荐答案
您只需要创建一个集合作为后备存储,并使用后备集合模拟枚举数据库集
You just need to create a collection to act as the backing store and mock the enumeration db set with the backing collection
public class MockDbSet<TEntity> : Mock<DbSet<TEntity>> where TEntity : class {
public MockDbSet(List<TEntity> dataSource = null) {
var data = (dataSource ?? new List<TEntity>());
var queryable = data.AsQueryable();
this.As<IQueryable<TEntity>>().Setup(e => e.Provider).Returns(queryable.Provider);
this.As<IQueryable<TEntity>>().Setup(e => e.Expression).Returns(queryable.Expression);
this.As<IQueryable<TEntity>>().Setup(e => e.ElementType).Returns(queryable.ElementType);
this.As<IQueryable<TEntity>>().Setup(e => e.GetEnumerator()).Returns(() => queryable.GetEnumerator());
//Mocking the insertion of entities
this.Setup(_ => _.Add(It.IsAny<TEntity>())).Returns((TEntity arg) => {
data.Add(arg);
return arg;
});
//...the same can be done for other members like Remove
}
}
所以现在您可以使用列表来保存数据
So now you can use a list to hold the data
// ARRANGE
var dataSource = new List<User>(); //<-- this will hold data
var user = new User()
{
FirstName = "Some",
LastName = "Guy",
EmailAddress = "some.guy@mockymoqmoq.com",
};
var mockSet = new MockDbSet<User>(dataSource);
var mockContext = new Mock<WebAPIDbContext>();
mockContext.Setup(c => c.Set<User>()).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<User>()), 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
}
这篇关于如何使用 Entity Framework 和 Moq 进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何使用 Entity Framework 和 Moq 进行单元测试?


- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- 输入按键事件处理程序 2022-01-01
- 如何用自己压缩一个 IEnumerable 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- C# 中多线程网络服务器的模式 2022-01-01
- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- MoreLinq maxBy vs LINQ max + where 2022-01-01