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

前端 未结 2 1900
后悔当初
后悔当初 2021-01-31 12:11

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 TestCustomer

2条回答
  •  一生所求
    2021-01-31 12:45

    This is one of the reasons why we move AutoMapper into a custom ActionResult or an ActionFilter. At some point, you only really want to test that you mapped Foo to FooDto, but not necessarily test the actual mapping. By moving AutoMapper into the layer boundaries (such as between controller an view), you can merely test what you're telling AutoMapper to do.

    This is similar to testing a ViewResult. You don't test from a controller that a view was rendered, but rather that you told MVC to render such-and-such view. Our action result becomes:

    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(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(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();
    
    var autoMapViewResult = (AutoMapViewResult) actionResult;
    
    autoMapViewResult.DestinationType.ShouldEqual(typeof(EventListModel[]));
    autoMapViewResult.View.ViewData.Model.ShouldEqual(queryResult);
    autoMapViewResult.View.ViewName.ShouldEqual(string.Empty);
    

提交回复
热议问题