c# - 如何在 C# 中使用 Moq 测试 Add 方法
问题描述
我尝试为存储库类中的 Add 方法编写单元测试。我正在使用 EF6 和起订量。我的测试方法看起来:
public static Mock<DbSet<T>> CreateDbSetMock<T>(IEnumerable<T> elements) where T : class
{
var elementsAsQueryable = elements.AsQueryable();
var dbSetMock = new Mock<DbSet<T>>();
dbSetMock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(elementsAsQueryable.Provider);
dbSetMock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(elementsAsQueryable.Expression);
dbSetMock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(elementsAsQueryable.ElementType);
dbSetMock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(elementsAsQueryable.GetEnumerator());
return dbSetMock;
}
[Test()]
public void AddTest()
{
// Arrange
Mock<DbSet<Tytul>> titlesMock = CreateDbSetMock(new List<Tytul>());
Mock<OzinDbContext> titlesContextMock = new Mock<OzinDbContext>();
titlesContextMock.Setup(x => x.Tytuly).Returns(titlesMock.Object);
titlesMock.Setup(x => x.Add(It.IsAny<Tytul>())).Returns((Tytul t) => t);
IRepository<Tytul> tytulRepository = TytulRepository(titlesContextMock.Object);
Tytul tytul = new Tytul
{
Identyfikator = "ABC"
};
// Act
tytulRepository.Add(tytul);
// in Add method:
//dbContext.Tytuly.Add(entity);
//dbContext.SaveChanges();
Tytul tytulInDb = tytulRepository.GetDetail(t => t.Identyfikator == "ABC");
// in GetDetail method:
//return dbContext.Tytuly.FirstOrDefault(predicate);
// Assert
Assert.AreEqual(tytulInDb.Identyfikator, tytul.Identyfikator);
}
我的问题是 GetDetail 方法返回 null,但我期望 tytulInDb 对象。怎么了?thist test怎么写正确?
解决方案
将 DbSet 的假数据源提取到局部变量中,以便稍后在测试设置中与之交互。将 a 添加Callback
到Add
设置中以将传递的参数添加到数据源,以便在调用时模拟要对实际数据进行操作。
// Arrange
var data = new List<Tytul>(); //<<< local variable
Mock<DbSet<Tytul>> titlesMock = CreateDbSetMock(data);
var titlesContextMock = new Mock<OzinDbContext>();
titlesContextMock.Setup(x => x.Tytuly).Returns(titlesMock.Object);
titlesMock
.Setup(x => x.Add(It.IsAny<Tytul>()))
.Returns((Tytul t) => t)
.Callback((Tytul t) => data.Add(t)); //<<< for when mocked Add is called.
IRepository<Tytul> tytulRepository = TytulRepository(titlesContextMock.Object);
//...Code removed for brevity
此外,在设置 DbSet Mock 时,请使用委托Returns
以允许多个枚举,因为仅返回值将仅允许仅前向枚举器的一次传递。
dbSetMock.As<IQueryable<T>>()
.Setup(m => m.GetEnumerator())
.Returns(() => elementsAsQueryable.GetEnumerator()); //<<< note delegate
推荐阅读
- azure-databricks - Azure Databricks 轻型运行时
- node.js - 从 pubsub 中提取消息而不会超时
- python - 替换 numpy 条目的省时方法
- java - Java Method.invoke 抛出 NullPointerException
- or-tools - CP_SAT:是否可以限制使用的 RAM?
- angular - 在一个角度函数中分别调用两个订阅而不混合它们
- pandas - 如何使用 pandas 将 excel 小时格式转换为分钟?
- java - 运行可运行的 jar 文件时 - 它不工作
- asterisk - 如何修复星号 1.8.18+ 编译错误?
- python - tkinter import Warning