.NET 5类库使用AutoMapper映射dynamic时xUnit测试对象比较失败
问题根因
- 你配置的
CreateMap<dynamic, FirstDTO>()仅适配源类型为动态类型(如ExpandoObject)的场景,当你传入强类型对象(比如测试里的FirstDTO实例)时,AutoMapper找不到对应强类型到FirstDTO的映射配置,就会返回所有属性为默认值的空对象。 - AutoMapper 9及以上版本默认关闭了自动创建缺失类型映射的配置,没有显式配置的映射关系不会自动生效。
- 若你的
FirstDTO是普通类未重写Equals方法,Assert.Equal默认比较引用地址而非属性值,哪怕属性值一致也会断言失败。
修复步骤
1. 修改AutoMapper配置
删掉原来的dynamic映射规则,开启自动类型映射配置,支持任意源类型到DTO的属性名匹配:
public static class Configuration { private static readonly Lazy<IMapper> Lazy = new Lazy<IMapper>(() => { var config = new MapperConfiguration(cfg => { // 开启自动创建缺失的类型映射,适配任意源类型到目标DTO的匹配 cfg.CreateMissingTypeMaps = true; cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly; // 无特殊自定义映射规则的话,不需要再引入MappingProfile }); // 调试阶段可以加这句验证配置合法性,正式运行可注释 config.AssertConfigurationIsValid(); return config.CreateMapper(); }); public static IMapper Mapper => Lazy.Value; }
2. 优化基类方法参数
dynamic会带来额外的性能开销和运行时风险,直接用object类型作为入参即可,AutoMapper原生支持任意对象作为映射源:
public class BaseLibraryClass : IBaseLibraryClass { public FirstDTO GetFirstObject(object objectSentIn) { return Configuration.Mapper.Map<FirstDTO>(objectSentIn); } // 其他DTO的映射方法也按同样逻辑修改 }
3. 修复单元测试断言逻辑
如果你的FirstDTO是普通类,要么将其改为C# 9+支持的record类型(默认实现值比较),要么改用Assert.Equivalent直接比较属性值,不需要额外重写Equals方法:
[Fact] public void TestSeparateObject() { // Arrange FirstDTO firstDTO = firstDTOBuilder.DefaultDTO().Build(); // Act FirstDTO result = baseLibraryClass.GetFirstObject(firstDTO); // Assert 等价比较所有属性值 Assert.Equivalent(firstDTO, result); }
可选优化
如果你需要对部分属性做特殊映射规则,再在MappingProfile里显式配置对应源类型到目标DTO的映射即可,不需要全局写dynamic相关的映射。
内容的提问来源于stack exchange,提问作者Chobo
相关产品推荐
相关产品推荐

