37

在 AutoMapper 中为 Map 函数设置模拟期望的最佳方法是什么?

我提取了 IMapper 接口,以便为该接口设置期望。我的映射器有依赖关系,所以我必须将它们传递给映射器。

当我使用 2 个不同的依赖项实现创建映射器类的 2 个实例时会发生什么?我假设两个映射器都将使用相同的依赖实例,因为 AutoMapper 映射是静态的。或者 AutoMapper 甚至可能会抛出异常,因为我尝试使用相同的对象设置 2 个不同的地图。?

解决这个问题的最佳方法是什么?

public interface IMapper {
    TTarget Map<TSource, TTarget>(TSource source);
    void ValidateMappingConfiguration();
}

public class MyMapper : IMapper {
    private readonly IMyService service;

    public MyMapper(IMyService service) {
        this.service = service
        Mapper.CreateMap<MyModelClass, MyDTO>()
            .ForMember(d => d.RelatedData, o => o.MapFrom(s =>
                service.getData(s.id).RelatedData))
    }

    public void ValidateMappingConfiguration() {
        Mapper.AssertConfigurationIsValid();
    }

    public TTarget Map<TSource, TTarget>(TSource source) {
        return Mapper.Map<TSource, TTarget>(source);
    }
}
4

6 回答 6

47

在 AutoMapper[?] 中为 Map 函数设置模拟期望的最佳方法是什么?

这是一种方法:

var mapperMock = new Mock<IMapper>();
mapperMock.Setup(m => m.Map<Foo, Bar>(It.IsAny<Foo>())).Returns(new Bar());
于 2010-02-26T09:40:29.037 回答
42

您不需要模拟 AutoMapper,您只需注入真正的 AutoMapper,如下所述

var myProfile = new MyProfile();
var configuration = new MapperConfiguration(cfg => cfg.AddProfile(myProfile));
IMapper mapper = new Mapper(configuration);

你可以在你的单元测试中注入这个映射器。使用 AutoMapper 等工具的全部意义在于您不必编写大量映射代码。如果您模拟 AutoMapper,您最终将不得不这样做。

于 2019-11-16T15:25:02.177 回答
3

http://richarddingwall.name/2009/05/07/mocking-out-automapper-with-dependency-injection/

指出另一种处理对 AutoMapper 的依赖关系的方法,它基本上将取代我提取自己的 IMapper 接口的尝试。相反,我将尝试使用现有的 IMappingEngine 作为我的类的依赖项,看看它是否有效。

于 2010-02-26T10:31:59.183 回答
2

您需要做的是像这样设置 AutoMapper(StructureMap 是 IoC)。然后你可以让你的服务依赖于IMappingEngine。从那里嘲笑它应该很容易。

public class AutoMapperConfigurationRegistry : Registry
    {
        public AutoMapperConfigurationRegistry()
        {
            ForRequestedType<Configuration>()
                .CacheBy(InstanceScope.Singleton)
                .TheDefault.Is.OfConcreteType<Configuration>()
                .CtorDependency<IEnumerable<IObjectMapper>>().Is(expr => expr.ConstructedBy(MapperRegistry.AllMappers));

            ForRequestedType<ITypeMapFactory>().TheDefaultIsConcreteType<TypeMapFactory>();

            ForRequestedType<IConfigurationProvider>()
                .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<Configuration>());

            ForRequestedType<IConfiguration>()
                .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<Configuration>());
        }
    }
于 2010-04-21T14:30:16.457 回答
0

您必须调用自动映射器配置的原因是,UNIT 测试用例实例在主应用程序启动文件/配置之外运行。因此,必须在任何单元测试开始运行之前调用和设置自动映射器配置。理想情况下,您将它放在 TestInitialize 方法中。

于 2020-09-01T22:21:32.483 回答
0

这是我如何使用 AutoFixture 和 Moq 提供 AutoMapper 实例作为 IMapper 的默认 Mock 的示例:

感谢 Lucian Bargaoanu 的提示:实际上您可以使用cfg.AddMaps(params Assembly[])Automapper 将搜索配置文件

  1. 创建一个ICustomization
public class MapperCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Register<IMapper>(() =>
        {
            var configuration = new MapperConfiguration(cfg =>
            {
                cfg.AddMaps(
                    Assembly.Load("BookSharing.Application"),
                    Assembly.Load("BookSharing.Infrastructure"));
            });

            return new Mapper(configuration);
        });
    }
}
  1. 注册自定义
fixture.Customize(new MapperCustomization());
于 2021-11-10T17:59:49.033 回答