AutoMapper配置文件和单元测试

9

我正在将我的AutoMapper从使用一个大的AutoMapperConfiguration类转换为使用实际的配置文件。全局现在看起来是这样的(现在暂时宽恕Open/Close违规)

Mapper.Initialize(x =>
                       {
                          x.AddProfile<ABCMappingProfile>();
                          x.AddProfile<XYZMappingProfile>();
                          // etc., etc.
                  });

关键要素是让我成功并克服先前一直阻碍我使用配置文件的障碍的是我的 Ninject 绑定。我以前从未能使绑定正常工作。之前我的绑定如下:

Bind<IMappingEngine>().ToConstant(Mapper.Engine).InSingletonScope();

我现在已经迁移到这个绑定:

Bind<IMappingEngine>().ToMethod(context => Mapper.Engine);

现在这个应用程序可以正常运行,我有用户档案,一切顺利。

问题出在我的单元测试上,我使用 NUnit,在构造函数依赖项中进行设置。

private readonly IMappingEngine _mappingEngine = Mapper.Engine;

然后在我的 [Setup] 方法中,我会构建我的MVC控制器并调用AutoMapperConfiguration类。

[SetUp]
public void Setup()
{
    _apiController = new ApiController(_mappingEngine);
    AutoMapperConfiguration.Configure();
}

我现在已经修改了它。

[SetUp]
public void Setup()
{
    _apiController = new ApiController(_mappingEngine);

    Mapper.Initialize(x =>
                          {
                              x.AddProfile<ABCMappingProfile>();
                              x.AddProfile<XYZMappingProfile>();
                              // etc., etc.
                          });
}

很遗憾,这似乎并不起作用。映射似乎没有被捡起来,因为当我碰到使用映射的方法时,AutoMapper会抛出一个异常,指出映射不存在。有什么建议可以更改测试中的映射器定义/注入以解决这个问题吗?我猜测IMappingEngine字段的定义是我的问题,但不确定我有哪些选项。

谢谢

1个回答

3
您遇到的问题是使用静态的Mapper.Engine,它是一种包含AutoMapper配置的单例。根据惯例,Mapper.Engine在配置后不应更改。因此,如果您想通过为每个单元测试提供AutoMapper.Profiler来配置Automapper,则应避免使用它。
更改相当简单:将您的类AutoMapperConfiguration的实例添加到其自己的实例AutoMapper.MappingEngine中,而不是使用全局静态Mapper.Engine
public class AutoMapperConfiguration 
{
    private volatile bool _isMappinginitialized;
    // now AutoMapperConfiguration  contains its own engine instance
    private MappingEngine _mappingEngine;

    private void Configure()
    {
        var configStore = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.AllMappers());

        configStore.AddProfile(new ABCMappingProfile());
        configStore.AddProfile(new XYZMappingProfile());

        _mappingEngine = new MappingEngine(configStore);

        _isMappinginitialized = true;
    }

    /* other methods */
}

ps: full sample is here


抱歉我还没有回复你。我进行了一次测试,你的Git确实可以运行,但是一旦我尝试将引擎作为构造函数参数提取出来,事情就会失控。今晚我会再回来进行进一步测试。 - Khepri
今天早上我验证了一下,作为一个独立的解决方案,你的git做了你期望的事情。然而,在我的场景中,我试图将IMappingEngine的实例作为构造函数参数传递并利用Ninject,但我仍然没有收到初始化映射。我拿了git,并添加了一个方法来返回初始化的MappingEngine,并尝试将其作为构造函数参数传递。结果是一样的。 - Khepri
你尝试过用新的独立实例MappingEngine替换所有对MapperMapper.InitializeMapper.Engine等)的调用/引用吗? - Akim
感谢您提供这段代码示例,我能够在我的测试中使用它来测试每个单独的映射配置文件,而不需要引用静态Mapper。 - Jon Erickson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接