Mocking AutoMapper with the IMapperEngine
Posted on Tuesday, 28th January 2014
I’ve been using Jimmy Bogard’s awesome AutoMapper library for a while now and find it an invaluable tool for mapping entities within my ASP.NET MVC application to DTOs (Data transfer objects) before passing them through the various layers within my application. This keeps my presentation layer nicely decoupled as it’s no longer referencing entities, and instead only knows about the data transfer objects.
If you’re new to AutoMapper and have been following a lot of the tutorials online then you your mappings might look a little something like this:
public class BlogService : IBlogService
{
...
public BlogPostDto GetPost(int id)
{
BlogPost blogPost = this.blogRepository.GetPost(id);
if (blogPost == null)
{
throw new EntityNotFoundException("blogPost");
}
return Mapper.Map<BlogPost, BlogPostDto>(blogPost);
}
...
}
Whilst doing it this way will work, if we want to stick to Uncle Bob’s SOLID princples and promote abstraction and code testability then we really want to do it a different way, as not to couple AutoMapper’s static Mapper.Map class to, in this instance, our BlogService class.
This is where AutoMappers IMappingEngine interface comes in handy.
IMappingEngine Interface
By using the IMapperEngine interface we’re able to “program to an interface and not implementation” (more on the importance of that here) by using our IoC container of choice to inject the IMappingEngine interface into our object. In this case it’s a Blog service object.
If you take a moment to look at what methods the IMappingEngine interface provides us you’ll see it provides us access to all of the mapping methods we need (specifically the Mapper.Map method used above). Great! Now all we need to do is inject our the MappingEngine and we’re good to go.
Injecting IMappingEngine using an IoC Container
In this instance I’m using StructureMap for my IoC container needs as I’m comfortable with it, but any IoC container will do.
To start with we need to map AutoMapper’s Mapper.Engine to the IMapperEngine interface within our custom Structuremap registry (I’ve included the full namespace to the registry below to make it easier for those trying to follow).
public class WebsiteRegistry : StructureMap.Configuration.DSL.Registry
{
public WebsiteRegistry()
{
this.For().Use();
Mapper.AddProfile(new AutoMapperMappingProfiles());
this.For().Use(() => Mapper.Engine);
}
}
Then all we have to do is register our new registry with StructureMap and call _StructureMapCoreSetup.Configure()_ in our application’s composition root. As this is an ASP.NET MVC application the composition root is the Global.asax.cs
public static class StructureMapCoreSetup
{
public static void Configure()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry();
});
}
}
Now that our instance of IMappingEngine is configured with our dependency injection container we’re able to inject AutoMapper whenever we need it, turning our first example below.
public class BlogService : IBlogService
{
private readonly IMappingEngine mappingEngine;
private readonly IBlogRepository blogRepository;
public BlogService(IMappingEngine mappingEngine, IBlogRepository blogRepository)
{
this.mappingEngine = mappingEngine;
this.blogRepository = blogRepository;
}
...
public BlogPostDto GetPost(int id)
{
BlogPost blogPost = this.blogRepository.GetPost(id);
if (blogPost == null)
{
throw new EntityNotFoundException("blogPost");
}
return this.mappingEngine.Map<BlogPost, BlogPostDto>(blogPost);
}
...
}
Now that we’re injecting the MappingEngine we’re easily able to mock it when writing tests, and can continue to program happy in the knowledge we’ve abstracted the AutoMappers mapping functionality and are programming to an interface rather than implementation.
See below for a simple test case using a mocked IMappingEngine instance:
[Test]
public void Get_Post_By_Id_Test()
{
var blogPost = new BlogPost();
var blogPostDto = new BlogPostDto();
/* Setup */
var mappingEngine = new Mock();
mappingEngine.Setup(x => x.Map<BlogPost, BlogPostDto>(blogPost)).Returns(blogPostDto);
this._blogRepository.Setup(x => x.GetPost(It.IsAny())).Returns(blogPost);
/* Test */
this._blogService = new BlogService(this._blogRepository.Object, mappingEngine.Object);
BlogPostDto blogPostResult = this._blogService.GetPost(5);
/* Assert */
Assert.NotNull(blogPostResult);
Assert.IsInstanceOf(blogPostResult);
}
Taking AutoMapper Further
If we wanted to further abstract AutoMapper from our web application then we could use the Facade Pattern to encapsulate the IMappingEngine and inject that instead. This means that if a time came where we wanted to completely replace AutoMapper with another object mapping engine, or even write our own then we wouldn’t need to violate the Liskov Substitution Principle. I will save this for another post though.
Enjoy this post? Don't be a stranger!
Follow me on Twitter at @_josephwoodward and say Hi! I love to learn in the open, meet others in the community and talk Go, software engineering and distributed systems related topics.