如何在xUnit中模拟含DeferredWhere与FirstOrDefaultAsync的LINQ代码
在xUnit中模拟DeferredWhere与FirstOrDefaultAsync的实现方案
假设_costOfConsomption是自定义仓储接口(比如ICostOfConsomptionRepository),我们可以用Moq框架完成模拟,以下是具体实现步骤:
1. 准备测试依赖与数据
首先确保项目已安装Moq和Moq.EntityFrameworkCore(依赖EF Core异步查询方法时需要),然后定义基础类型:
// 实体类示例 public class CostOfConsomption { public int Id { get; set; } // 其他业务属性 } // 仓储接口(需包含DeferredWhere方法) public interface ICostOfConsomptionRepository { IQueryable<CostOfConsomption> DeferredWhere(Expression<Func<CostOfConsomption, bool>> predicate); }
2. 模拟找到数据的场景
当DeferredWhere传入匹配model.CostOfConsomptionId的条件时,返回包含目标实体的查询集合,确保FirstOrDefaultAsync能正常返回实体:
[Fact] public async Task UpdateCost_WhenCostExists_ReturnsTargetCost() { // Arrange var testCostId = 1; var testModel = new { CostOfConsomptionId = testCostId }; var testCosts = new List<CostOfConsomption> { new CostOfConsomption { Id = testCostId } }.AsQueryable(); var repoMock = new Mock<ICostOfConsomptionRepository>(); repoMock.Setup(repo => repo.DeferredWhere(It.IsAny<Expression<Func<CostOfConsomption, bool>>>())) .Returns(testCosts); // 将mock注入被测服务 var service = new YourBusinessService(repoMock.Object); // Act var result = await service.TargetMethod(testModel); // 调用包含目标代码的业务方法 // Assert Assert.NotNull(result); Assert.Equal(testCostId, result.Id); }
3. 模拟找不到数据的场景
当DeferredWhere返回空集合时,验证代码是否正确抛出NotFoundException:
[Fact] public async Task UpdateCost_WhenCostDoesNotExist_ThrowsNotFoundException() { // Arrange var testCostId = 999; var testModel = new { CostOfConsomptionId = testCostId }; var emptyCosts = new List<CostOfConsomption>().AsQueryable(); var repoMock = new Mock<ICostOfConsomptionRepository>(); repoMock.Setup(repo => repo.DeferredWhere(It.IsAny<Expression<Func<CostOfConsomption, bool>>>())) .Returns(emptyCosts); var service = new YourBusinessService(repoMock.Object); // Act & Assert await Assert.ThrowsAsync<NotFoundException>(() => service.TargetMethod(testModel)); }
注意事项
- 如果
DeferredWhere是静态扩展方法,直接模拟会比较困难,建议将这类查询逻辑封装到仓储接口中,提升代码可测试性。 - 使用
Moq.EntityFrameworkCore可以更好地支持EF Core异步查询方法,无需手动模拟FirstOrDefaultAsync的返回任务。
内容的提问来源于stack exchange,提问作者Rezabk
相关产品推荐
相关产品推荐

