将 AutoMapper 从 v6 升级到 v9 并使用解析上下文进行单元测试

wom*_*72a 4 automapper-9

我希望有人能帮助我。我们目前正在将 AutoMapper 从 v6 升级到 v9 - 我们会升级到 v10,但无法创建新的ResolutionContext影响我们的单元测试。也就是说,在 v9 中,我们在单元测试 AutoMapper 转换器方面仍然遇到以下问题......

转换器类:

public class FooBarConverter :
    ITypeConverter<FooSourceObject, BarDestinationObject>
{
    /// <inheritdoc/>
    public virtual BarDestinationObjectConvert(FooSourceObjectsource, BarDestinationObjectdestination, ResolutionContext context)
    {
        EnsureArg.IsNotNull(source, nameof(source));

        switch (source.Type)
        {
            case SomeType.None:
                return context.Mapper.Map<NoneBarDestinationObject>(source);
            case SomeType.FixedAmount:
                return context.Mapper.Map<FixedBarDestinationObject>(source);
            case SomeType.Percentage:
                return context.Mapper.Map<PercentageBarDestinationObject>(source);
            default:
                throw new ArgumentOutOfRangeException(nameof(source));
        }
    }
Run Code Online (Sandbox Code Playgroud)

在 AutoMapper 6 之前,我们进行了以下单元测试(使用 Xunit):

public class FooBarConverterTests
{
    private readonly FooBarConverter target;

    private readonly Mock<IRuntimeMapper> mockMapper;
    private readonly ResolutionContext resolutionContext;

    public FooBarConverterTests()
    {
        this.mockMapper = new Mock<IRuntimeMapper>();
        this.resolutionContext = new ResolutionContext(null, this.mockMapper.Object);
        this.target = new FooBarConverter();
    }

    [Fact]
    public void FixedAmountFooModel_ConvertsTo_FixedBarDomainModel()
    {
        // Arrange
        var input = new Foo
        {
            Type = SomeType.FixedAmount
        };

        var expected = new DomainModels.FixedBarDestinationObject();

        this.mockMapper.Setup(x => x.Map<FixedBarDestinationObject>(It.IsAny<FooSourceObjectsource>()))
            .Returns(expected);

        // Act
        var actual = this.target.Convert(input, It.IsAny<BarDestinationObjectdestination>(), this.resolutionContext);

        // Assert
        actual.ShouldSatisfyAllConditions(
            () => actual.ShouldNotBeNull(),
            () => actual.ShouldBeAssignableTo<DomainModels.FixedBarDestinationObject>());

        this.mockMapper.Verify(x => x.Map<DomainModels.FixedBarDestinationObject>(input));
    }
}
Run Code Online (Sandbox Code Playgroud)

本质上,这工作得很好,但是自从升级到 v9 以来,映射设置在通过解析上下文时丢失了。这意味着 的结果调用Mapper.Map<FixedBarDestinationObject>()总是返回null.

我知道ResolutionContext可能略有变化,但我不明白如何解决此问题并确保模拟映射传递到底层转换器。

感谢您的任何帮助或建议。

wom*_*72a 5

感谢卢西安,我终于明白了这一点:

public class FooBarConverterTests
{
    private readonly FooBarConverter target;

    private readonly IMapper mapper;

    public FooBarConverterTests()
    {
        this.mapper = this.GetMapperConfiguration().CreateMapper();
        
        this.target = new FooBarConverter();
    }

    [Fact]
    public void FixedAmountFooModel_ConvertsTo_FixedBarDomainModel()
    {
        // Arrange
        var input = new Foo
        {
            Type = SomeType.FixedAmount
        };

        var expected = new DomainModels.FixedBarDestinationObject();

        // Act
        var actual = this.Mapper.Map<BarDestinationObjectdestination>(input);

        // Assert
        actual.ShouldSatisfyAllConditions(
            () => actual.ShouldNotBeNull(),
            () => actual.ShouldBeAssignableTo<DomainModels.FixedBarDestinationObject>());
    }
    
        private MapperConfiguration GetMapperConfiguration()
        {
            return new MapperConfiguration(opt =>
            {
                opt.AddProfile<CustomAutomapperProfile>();
                opt.ConstructServicesUsing(t =>
                {
                    if (t == typeof(FooBarConverter))
                    {
                        return this.target;
                    }

                    return null;
                });
            });
        }
}
Run Code Online (Sandbox Code Playgroud)

因此,我正在加载映射器配置文件(需要转换器)并通过它调用转换器,这可确保加载映射器配置文件。

作为奖励,这也意味着我完全不需要更新ResolutionContext,并为升级到 v10 铺平道路。