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
相关产品推荐
相关产品推荐

