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

C#单元测试中如何Mock foreach循环内调用的IMapper接口?

C# 单元测试中循环调用IMapper的Mock正确配置方法

问题场景

业务代码中通过IMapper逐行循环映射实体,核心代码如下:

foreach (var req in listRequestMasters)
{
    var customReq = _mapper.Map<GridModel>(req);
}

编写单元测试配置Mock时遇到两个问题:

  • 第一种配置下断言可执行通过,但返回结果不符合预期,同一条记录重复出现多次:
    _mockMapper.Setup(x => x.Map<GridModel>(It.IsAny<RequestMaster>())).Returns(requestGridModelMockData.FirstOrDefault());
    
  • 第二种配置直接抛出Moq.MockException异常,严格Mock模式下提示找不到对应调用的Setup配置:

    Moq.MockException : IMapperBase.Map(RequestMaster)
    invocation failed with mock behavior Strict. All invocations on the
    mock must have a corresponding setup.
    对应错误配置代码:

    _mockMapper.Setup(x => x.Map<List<GridModel>>(It.IsAny<RequestMaster>())).Returns(requestGridModelMockData);
    

测试预期为接口返回结果与Mock数据源requestGridModelMockData完全一致,现有断言逻辑:

var result = await Service.GetHistoryRequestDetails(historyVMMockData);
Assert.Equal(JsonConvert.SerializeObject(requestGridModelMockData), JsonConvert.SerializeObject(result));

错误原因

  • 第一种配置错误:Returns传入了固定的单个实体实例,Moq每次匹配到Map调用都会返回这同一个实例,循环执行多少次就返回多少次同一个对象,必然出现单条数据重复的问题。
  • 第二种配置错误:业务代码实际调用的是泛型参数为GridModel的单对象映射方法,但Setup配置的是泛型参数为List<GridModel>的集合映射方法,方法签名完全不匹配,严格Mock模式下找不到对应配置就会抛出异常。

正确配置方案

方案1:按调用顺序依次返回Mock数据

使用Moq的ReturnsInOrder方法,按传入顺序逐次返回Mock数据集中的元素,和循环逐行映射的逻辑完全匹配:

// 需确保已引入Moq命名空间
_mockMapper.Setup(x => x.Map<GridModel>(It.IsAny<RequestMaster>()))
    .ReturnsInOrder(requestGridModelMockData.ToArray());

注意:传入的数组长度需要和循环执行的次数保持一致,超出调用次数后会返回类型默认值。

方案2:根据入参动态匹配返回结果

如果Mock数据集和传入的源实体是一一对应的,可以在Returns中传入委托,根据传入的源对象动态匹配对应的返回值,灵活性更高,不受调用顺序、次数限制:

_mockMapper.Setup(x => x.Map<GridModel>(It.IsAny<RequestMaster>()))
    .Returns((RequestMaster source) => 
    {
        // 按实际业务的唯一标识匹配对应Mock数据即可,示例以RequestId匹配为例
        return requestGridModelMockData.First(item => item.RequestId == source.Id);
    });

该写法完全兼容严格Mock模式,逻辑更贴近AutoMapper的真实映射行为。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:01:11