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

xUnit测试中Mock多源映射AutoMapper的配置写法问题

AutoMapper多源映射Mock精确匹配失败问题

问题描述

为使用多源映射的业务逻辑编写xUnit单元测试时,AutoMapper的Mock配置无法通过精确入参匹配生效,仅匹配任意object类型入参时测试可正常运行。

使用的AutoMapper映射配置如下:

CreateMap<(Foo foo, Boo boo), Dto>()
 .ForMember(d => d.Name, o => o.MapFrom(s => s.foo.Name))
 .ForMember(d => d.Age, o => o.MapFrom(s => s.boo.Age));

初始编写的测试代码如下:

[Fact]
public void Handle_Test1()
{
    //Arrange
    var mocker = new AutoMocker(); 
    var sut = mocker.CreateInstance<Handler>();
    var mapperMock = mocker.GetMock<IMapper>();

    var foo = new Foo { Name = "Test" };
    var boo = new Boo { Age = 25 };
    var dto = new Dto { Name = "Test", Age = 25 };
    
    mapperMock.Setup(x => x.Map<Dto>(new Tuple<Foo, Boo> (foo, boo ))).Returns(dto);

    // 另一种尝试的写法
    //mapperMock.Setup(x => x.Map<Dto>(new { foo, boo })).Returns(dto);
}

临时可用但不符合精确匹配需求的写法:

mapperMock.Setup(x => x.Map<Dto>(It.IsAny<object>())).Returns(dto)

两种精确匹配写法的错误原因

  • 第一种写法类型不匹配:映射配置里定义的源类型是C#值元组ValueTuple<Foo, Boo>(即写法(Foo foo, Boo boo)),属于值类型;而Mock时传入的Tuple<Foo, Boo>是旧版的类类型元组,二者是完全不同的类型,AutoMapper实际调用Map方法传入的是值元组,自然无法命中该Setup。
  • 第二种写法类型不匹配:传入的new { foo, boo }是编译器生成的匿名类型,和值元组类型没有关联,类型不一致同样无法命中Setup。

正确的精确匹配写法

值元组支持基于字段值的结构相等判断,只要字段值一致就会判定为相等,直接传入对应值元组即可完成精确匹配:

// 直接传入值元组做精确匹配
mapperMock.Setup(x => x.Map<Dto>((foo, boo))).Returns(dto);

如果需要对入参做自定义规则校验,可以用It.Is<>编写匹配断言:

mapperMock.Setup(x => x.Map<Dto>(It.Is<(Foo foo, Boo boo)>(src => 
    src.foo.Name == "Test" && src.boo.Age == 25
))).Returns(dto);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 08:24:26