Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use AutoMapper in my unit tests?

I'm writing unit tests for ASP.NET MVC controller methods.

Those controllers have a dependency on IMapper - an interface I've created to abstract AutoMapper, passed in via constructor injection using Castle Windsor.

Action methods use IMapper to map from domain objects to ViewModel objects and back again, aiming to keep things DRY and keep action methods succinct.

In my unit tests, should I

  1. Configure AutoMapper with the correct bindings (they're built using AutoMapper profiles, so testable and reusable between website and unit test projects) and pass that in as a proper AutoMapper implementation of IMapper.

  2. Pass in mock objects (I'm using Moq) for the IMapper instance, depending on the test (this would mean duplicating some work in the test setup code to make sure the objects returned from the mock mapper relate to the objects the mock mapper is pretending to map).

  3. Hand-configure AutoMapper with just the mappings I think I'll need for each test (lot of work and means I'm not testing the mappings that will really be in use).

What's the opinion on using infrastructure code in unit tests? At what point does it become an integration test (i.e. testing integration of AutoMapper and my controllers)?

It feels like 2 is the purist view, though I think I need to learn more about Moq and how to get it to return values that relate to the actual values passed into the methods that it's mocking.

like image 815
Neil Barnwell Avatar asked Jan 12 '11 00:01

Neil Barnwell


2 Answers

I'm in favour of #2 like jeriley

Adding to the Moq, if you need to return an object based on values passed to it you can write your setup like so:

mockObject.Setup(x => x.MapObject(It.IsAny())
          .Returns((ProductDto productDto) => 
           {
               var product = new Product()
               {
                   Id = productDto.Id,
                   Name = productDto.Name
               };

               return product
           });

Little bit messy but handy.

like image 87
Phill Avatar answered Oct 02 '22 21:10

Phill


I could tend to agree with #2. You know automapper works, you know your injection works ( got tests for that right? :-) ) I would focus more on specifics, things that aren't just SomeClass.Property = AnotherClass.Property -- THOSE special cases should be tested not basic copy functions. Don't test framework stuff.

As for more test code - I feel that's completely ok. Tests should be setup within the given tests (also within reason) for just that given unit.

Regarding Moq, syntax is easy, don't overthink it. var obj = new Mock(); then set your properties like obj.Setup(x => x.Property).returns("hello") unless you have a more specific issue? Moq also has setup all properties on it as well, so you may not even need automapper

-edit- found it, it's obj.SetupAllProperties();

like image 28
jeriley Avatar answered Oct 02 '22 21:10

jeriley