Monday, May 26, 2014

AutoMapper - IOC vs. Static Mapper

I've been using AutoMapper for almost a year and I never noticed that it has an interface for the mapping engine cleverly named IMappingEngine.  I stumbled upon this post by Jimmy Bogard.  In the post Jimmy shows how to use AutoMapper with an IoC (Inversion of Control) container and more specifically, StructureMap.

I'm in two minds over this matter.  Technically, a test written against code that uses the static AutoMapper mapper class would be considered integration tests.  You loose one tiny seam in your code... Additionally, code written in this manner will hide its dependency on the external mapper.  However, how big of a deal is it?  When writing code that uses dependency injection, we are always monitoring our constructors for injection bloat but that's a separate issue. On one hand, if I use the static over the injected, I have one less parameter in the class constructor.  On the other, I hide a dependency and I can't write a mock to verify that AutoMapper was called.

I've tried out both instances of this in my code and for now I'm leaning toward injection for one reason alone. I'm not a big fan of writing a test to find it's failing because I forgot to configure AutoMapper in my unit test. Having it in the constructor forces the issue and it reminds me to either write a mock for it or configure and inject the static mapping engine. Typically, when writing my unit tests I use Moq. However, sometimes mocking auto mapper seems to make little sense as the mapping is an integral part of the code. Interestingly, in the comments on Jimmy Bogard's post, there is a conversion about this very issue.

Which should you use?  The answer is, it depends...  What is important to you?  What are you trying to test?

In case you find yourself wanting to use your IoC container, here is an example from StackOverflow  on how to register the IMappingEngine for resolution in Unity. 

container.RegisterType<IMappingEngine>(new InjectionFactory(_ => Mapper.Engine));

This works with any static global configuration done using Mapper.CreateMap<>(). Just ensure that your configuration is called once before using the mapping engine.

No comments:

Post a Comment