Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoMapper Profiles and Unit Testing

I'm rolling over my AutoMappers from using one large AutoMapperConfiguration class to using actual profiles. Global now looks like so (forgive the Open/Close violation for now)

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

The key piece that got me over the top and the hurdle that had previously always stopped me from using profiles was my ninject binding. I could never get the binding to work. Prior I had this binding:

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

I've since migrated to this binding:

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

This now works, the app is functional, I have profiles, and things are good.

The hitch is now in my unit tests. Using NUnit, I'd setup my constructor dependencies.

private readonly IMappingEngine _mappingEngine = Mapper.Engine;

and then in my [Setup] method I'd construct my MVC controller and call the AutoMapperConfiguration class.

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

which I've now modified to.

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

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

Unfortunately, this does not seem to work. The mappings do not appear to be getting picked up as when I hit a method that uses mappings, AutoMapper throws an exception stating the mapping doesn't exist. Any suggestions on how/what to change the the mapper definition/injection in the test to resolve this? I'm guessing the definition of the IMappingEngine field is my problem but unsure of what options I have.

Thanks

like image 679
Khepri Avatar asked Apr 22 '13 17:04

Khepri


1 Answers

Issue that you have is result of using static Mapper.Engine which is some kind of singleton that contains configuration for AutoMapper. By convention, Mapper.Engine should not be changed after it has been configured. So, if you'd like to configure Automapper by providing AutoMapper.Profiler for each of unittest, you should avoid using it.

Changes are quite simple: add to instance your class AutoMapperConfiguration it's own instance AutoMapper.MappingEngine instead of using global static 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

like image 197
Akim Avatar answered Nov 15 '22 03:11

Akim