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

.NET 5类库使用AutoMapper映射dynamic时xUnit测试对象比较失败

问题根因

  1. 你配置的CreateMap<dynamic, FirstDTO>()仅适配源类型为动态类型(如ExpandoObject)的场景,当你传入强类型对象(比如测试里的FirstDTO实例)时,AutoMapper找不到对应强类型到FirstDTO的映射配置,就会返回所有属性为默认值的空对象。
  2. AutoMapper 9及以上版本默认关闭了自动创建缺失类型映射的配置,没有显式配置的映射关系不会自动生效。
  3. 若你的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 05:36:05