AutoMapper Profiles and Unit Testing
Asked Answered
F

1

9

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

Fleabag answered 22/4, 2013 at 17:55 Comment(0)
C
3

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

Counterchange answered 24/4, 2013 at 4:4 Comment(4)
Sorry I haven't gotten back to you yet. I ran a test and your Git does function, but as soon as I try to pull the engine out as a constructor parameter things go off the rails. I'll circle back around tonight for further testing.Fleabag
I've verified this morning that as a stand alone solution, your git does what you'd expect. However, for my scenario where I'm trying to pass an instance of IMappingEngine as a constructor parameter utilizing Ninject, I'm still not receiving initialized mappings. I took the git, and added a method to return out the initialized MappingEngine and attempted to pass that as a constructor param. The results were the same.Fleabag
Have you tried to replace all calls/refences to Mapper (Mapper.Initialize, Mapper.Engine, etc) with new stand-alone instance of MappingEngine?Counterchange
thanks for this code sample, I was able to use this in my tests to test each individual mapping profile without referencing the static MapperBreeding

© 2022 - 2024 — McMap. All rights reserved.