使用Moq模拟AutoMapper Mapper.Map调用

时间:2010-02-26 09:17:33

标签: c# moq automapper

什么是在AutoMapper中为Map函数设置模拟预览的最佳方法。

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

当我使用2个不同的依赖项实现创建2个mapper类实例时会发生什么?我认为两个映射器将使用相同的依赖项实例,因为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);
    }
}

5 个答案:

答案 0 :(得分:31)

在AutoMapper [?]

中为Map函数设置模拟异常的最佳方法是什么?

这是一种方式:

var mapperMock = new Mock<IMapper>();
mapperMock.Setup(m => m.Map<Foo, Bar>(It.IsAny<Foo>())).Returns(new Bar());

答案 1 :(得分:2)

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

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

答案 2 :(得分: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>());
        }
    }

答案 3 :(得分:2)

您无需模拟AutoMapper,只需按照说明here注入真实的代码即可:

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

您可以在单元测试中注入该映射器。使用诸如AutoMapper之类的工具的重点在于您不必编写大量映射代码。如果您模拟AutoMapper,最终将不得不这样做。

答案 4 :(得分:0)

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