After using Automapper to map a ViewModel how and what should I test?

After using Automapper to map a ViewModel how and what should I test?

I am attempting to test the Index action of a controller. The action uses AutoMapper to map a domain Customer object to a view model TestCustomerForm. While this works I am concerned about the best way to test the results that I am receiving from the Index action.

The controller's index action looks like this:

public ActionResult Index() {     TestCustomerForm cust = Mapper.Map<Customer,         TestCustomerForm>(_repository.GetCustomerByLogin(CurrentUserLoginName));      return View(cust); } 

And its TestMethod looks like this:

[TestMethod] public void IndexShouldReturnCustomerWithMachines() {     // arrange     var customer = SetupCustomerForRepository(); // gets a boiler plate customer     var testController = CreateTestController();      // act     ViewResult result = testController.Index() as ViewResult;      // assert     Assert.AreEqual(customer.MachineList.Count(),         (result.ViewData.Model as TestCustomerForm).MachineList.Count()); } 

In the CreateTestController method I use Rhino.Mocks to mock a customer repository and set it up to return the customer from SetupCustomerForRepository. In this manner I know that the repository will return the intended customer when the Index action calls _repository.GetCustomerByLogin(CurrentUserLoginName). Therefore, I figure asserting an equal count is adequate to satisfy IndexShouldReturnCustomerWithMachines.

All of that said I am concerned as to what I should be testing.

  1. It seems presumptuous to cast the result.ViewData.Model as TestCustomerForm. Is this really an issue? This concerns me because in this instance I am not truly doing test driven development and it seems like I am counting on a particular implementation to satisfy the test.
  2. Are there more appropriate tests to ensure correct mapping?
  3. Should I be testing each mapped property from the TestCustomerForm?
  4. Are there more general controller action tests that I should be doing?

“ASP.NET Webforms MVP” as an alternative to “ASP.NET MVC” [closed]

1: Mvc Routing problem
This is one of the reasons why we move AutoMapper into a custom ActionResult or an ActionFilter.

How to dynamically determine which HTML 'wrapper' file to use based on the Action Method being executed?
At some point, you only really want to test that you mapped Foo to FooDto, but not necessarily test the actual mapping.

Can an Action Filter have access to a private object in the Controller?
By moving AutoMapper into the layer boundaries (such as between controller an view), you can merely test what you're telling AutoMapper to do..
Is it possible to optimize ASP.NET WebForms to perform as fast as ASP.NET MVC?
This is similar to testing a ViewResult.

Return all fields from strongly typed object from View in MVC
You don't test from a controller that a view was rendered, but rather that you told MVC to render such-and-such view.

ASP.NET MVC - Routing still confusing for me
Our action result becomes:.
Changing a page from DropDownList using jQuery
public class AutoMapViewResult : ActionResult {     public Type SourceType { get; private set; }     public Type DestinationType { get; private set; }     public ViewResult View { get; private set; }      public AutoMapViewResult(Type sourceType, Type destinationType, ViewResult view)     {         SourceType = sourceType;         DestinationType = destinationType;         View = view;     }      public override void ExecuteResult(ControllerContext context)     {         var model = Mapper.Map(View.ViewData.Model, SourceType, DestinationType);          View.ViewData.Model = model;          View.ExecuteResult(context);     } } 
With a helper method on a base controller class:.
protected AutoMapViewResult AutoMapView<TDestination>(ViewResult viewResult) {     return new AutoMapViewResult(viewResult.ViewData.Model.GetType(), typeof(TDestination), viewResult); } 
Which then makes the controller now only specify what to map to/from, instead of performing the actual mapping:.
public ActionResult Index(int minSessions = 0) {     var list = from conf in _repository.Query()                 where conf.SessionCount >= minSessions                 select conf;      return AutoMapView<EventListModel[]>(View(list)); } 
At this point, I only need to test, "make sure that you're mapping this Foo object to this destination FooDto type", without needing to actually perform the mapping.. EDIT:. Here's an example of a test snippet:.
var actionResult = controller.Index();  actionResult.ShouldBeInstanceOf<AutoMapViewResult>();  var autoMapViewResult = (AutoMapViewResult) actionResult;  autoMapViewResult.DestinationType.ShouldEqual(typeof(EventListModel[])); autoMapViewResult.View.ViewData.Model.ShouldEqual(queryResult); autoMapViewResult.View.ViewName.ShouldEqual(string.Empty); 


I would probably separate the coupling between AutoMapper and the controller by introducing an abstraction:.
public interface IMapper<TSource, TDest> {     TDest Map(TSource source); }  public CustomerToTestCustomerFormMapper: IMapper<Customer, TestCustomerForm> {     static CustomerToTestCustomerFormMapper()     {         // TODO: Configure the mapping rules here     }      public TestCustomerForm Map(Customer source)     {         return Mapper.Map<Customer, TestCustomerForm>(source);     } } 
Next you pass this into the controller:.
public HomeController: Controller {     private readonly IMapper<Customer, TestCustomerForm> _customerMapper;     public HomeController(IMapper<Customer, TestCustomerForm> customerMapper)     {         _customerMapper = customerMapper;     }      public ActionResult Index()     {         TestCustomerForm cust = _customerMapper.Map(             _repository.GetCustomerByLogin(CurrentUserLoginName)         );         return View(cust);     } } 
And in your unit test you would use your favorite mocking framework to stub this mapper..

53 out of 100 based on 18 user ratings 943 reviews