You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Moq结合工作单元与泛型仓储做单元测试时如何获取单个对象

问题原因

  • FirstOrDefault 是LINQ提供的扩展方法,Moq 不支持直接在Setup表达式里模拟扩展方法,只能模拟接口/类本身定义的可重写成员,也就是你只能Setup仓储的Get方法本身,不能连后面的FirstOrDefault一起写进Setup的表达式树里。
  • 参数匹配规则不兼容。Lambda表达式是引用类型,你Setup里写的store => store.WebStoreId == webStoreId和业务代码运行时动态生成的Lambda不是同一个实例,默认按引用匹配的规则下会匹配失败,导致Mock返回空值。

正确实现方式

方式1:通用匹配(最简单)

只需要Mock仓储的Get方法返回你构造的测试集合即可,后续的FirstOrDefault是真实执行的LINQ逻辑,不需要模拟:

[Test]
public void GetWebstore_GetSingle()
{
    var webStoreId = 1;
    var customerName = "A";
    var listWebstore = new List<WebStore>() { new WebStore { WebStoreId = webStoreId, CustomerName = customerName } };
    var webstore = new WebStore { WebStoreId = webStoreId, CustomerName = customerName };
   
    // 设置Mock,匹配任意传入Get方法的参数,返回预设的集合
    _unitOfWork.Setup(uow => uow.GetRepository<WebStore>()
        .Get(
            It.IsAny<Expression<Func<WebStore, bool>>>(), 
            It.IsAny<Func<IQueryable<WebStore>, IOrderedQueryable<WebStore>>>(),
            It.IsAny<string>(),
            It.IsAny<int>(),
            It.IsAny<int>()
        ))
        .Returns(listWebstore);

    // 后续执行测试逻辑即可
}

方式2:严格匹配筛选逻辑(更严谨)

如果需要验证业务代码确实是按WebStoreId做筛选,可以对传入的Lambda做逻辑匹配:

[Test]
public void GetWebstore_GetSingle()
{
    var webStoreId = 1;
    var customerName = "A";
    var expectedWebstore = new WebStore { WebStoreId = webStoreId, CustomerName = customerName };
    var listWebstore = new List<WebStore>() { expectedWebstore };
   
    // 定义筛选条件匹配规则:传入的lambda执行后能匹配我们的测试对象
    Func<Expression<Func<WebStore, bool>>, bool> FilterMatcher = filter => 
        filter.Compile().Invoke(expectedWebstore);

    _unitOfWork.Setup(uow => uow.GetRepository<WebStore>()
        .Get(
            It.Is<Expression<Func<WebStore, bool>>>(f => FilterMatcher(f)), 
            It.IsAny<Func<IQueryable<WebStore>, IOrderedQueryable<WebStore>>>(),
            It.IsAny<string>(),
            It.IsAny<int>(),
            It.IsAny<int>()
        ))
        .Returns(listWebstore);
}

额外注意点

你业务代码里的GetAllWebstore方法返回值标注为WebStore,但实际返回的是GetAll()的集合结果,属于笔误,需要修正返回类型为IEnumerable<WebStore>,否则运行时会抛出类型转换异常。

内容的提问来源于stack exchange,提问作者sadko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 13:54:01