Injecting AutoMapper profiles in tests


2 min read

In the newer services at my client, AutoMapper is used to map DTO's to database objects and back. Because mocking a mapping isn't obvious, a lot of behaviour wasn't tested and that's unacceptable. Let's find out how to properly inject an IMapper with actual mappings.

The full setup is that we create Profiles that know how the mapping of objects happen. AutoMapper, combined with an IOC framework, automagically gathers all profiles and an IMapper instance is injected into the right places.

Now what happens when I want to test something that needs to be handled by the IMapper object. The easiest way is to figure out where the object comes from, say a database or passed along to the method, retrieve a dummy object and let the mapper mock produce the real object that will be used in the test. This would look like this (C# pseudo code):

// test setup
var actualObject = new MyObject();
var parameters = new ParameterObject();
var mockRepository = new Mock<IRepository>();
new mockMapper = new Mock<IMapper>();
mockMapper.Setup(x => x.Map(It.Any())).Returns(actualObject);
new MyService(mockRepository, mockMapper).Execute(parameters);

class MyService
  void Execute(Any parameters)
     var repoObject = _repository.Get();
     var actualObject = _mapper.Map(repoObject);
     var otherActualObject = _mapper.Map(parameters);
     // do stuff

The biggest problem I have with this is that the Profile isn't tested. I've had multiple problems with bad mappings, missing mappings or where I had made a mistake in wiring it up. So I want to include the mapping in my tests without duplicating the mapping code.

After some googling, I found a surprisingly easy way to do this.

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

It only takes three steps. The first is to create an instance of the mapper you want to use. The second step is to create a MappingConfiguration and register my Profile. The third and last step is to create an instance of a Mapper and pass the MapperConfiguration to the Mapper. This Mapper instance can then be passed to my test and will map with my custom Profile.

Now I have more confidence that my tests properly verify more of my code.