这就是我们将 AutoMapper 移至自定义 ActionResult 或 ActionFilter 的原因之一。在某些时候,您只想测试是否将 Foo 映射到 FooDto,但不一定测试实际的映射。通过将 AutoMapper 移动到层边界(例如控制器和视图之间),您可以仅测试告诉 AutoMapper 执行的操作。
这类似于测试 ViewResult。您不从控制器测试视图是否已渲染,而是告诉 MVC 渲染这样那样的视图。我们的行动结果变成:
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);
}
}
使用基本控制器类上的辅助方法:
protected AutoMapViewResult AutoMapView<TDestination>(ViewResult viewResult)
{
return new AutoMapViewResult(viewResult.ViewData.Model.GetType(), typeof(TDestination), viewResult);
}
这使得控制器现在只指定要映射到/从什么映射,而不是执行实际的映射:
public ActionResult Index(int minSessions = 0)
{
var list = from conf in _repository.Query()
where conf.SessionCount >= minSessions
select conf;
return AutoMapView<EventListModel[]>(View(list));
}
此时,我只需要测试“确保将此 Foo 对象映射到此目标 FooDto 类型”,而不需要实际执行映射。
EDIT:
这是测试片段的示例:
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);