Как сделать unit test собственный ActionFilter в ASP.Net MVC
Итак, я создаю пользовательский ActionFilter, основанный главным образом на этом проекте http://www.codeproject.com/KB/aspnet/aspnet_mvc_restapi.aspx.
Мне нужен настраиваемый фильтр действий, который использует заголовки http accept для возврата JSON или Xml. Типичное действие контроллера будет выглядеть следующим образом:
[AcceptVerbs(HttpVerbs.Get)]
[AcceptTypesAttribute(HttpContentTypes.Json, HttpContentTypes.Xml)]
public ActionResult Index()
{
var articles = Service.GetRecentArticles();
return View(articles);
}
Пользовательский фильтр переопределяет OnActionExecuted и сериализует объект (в этом примере статьи) как JSON или Xml.
Мой вопрос: как я могу это проверить?
- Какие тесты я пишу? Я новичок в TDD и не уверен на 100%, что я должен тестировать и что не тестировать. Я придумал
AcceptsTypeFilterJson_RequestHeaderAcceptsJson_ReturnsJson()
, AcceptsTypeFilterXml_RequestHeaderAcceptsXml_ReturnsXml()
и AcceptsTypeFilter_AcceptsHeaderMismatch_ReturnsError406()
.
- Как проверить ActionFilter в MVC, который тестирует заголовки Http Accept?
Спасибо.
Ответы
Ответ 1
Вам просто нужно проверить фильтр. Просто создайте экземпляр и вызовите метод OnActionExecuted()
с тестовыми данными, затем проверьте результат. Это помогает максимально разобрать код. Вот пример, который я написал. Большая часть тяжелого подъема выполняется внутри класса CsvResult
, который может быть проверен индивидуально. Вам не нужно проверять фильтр на фактическом контроллере. Выполнение этой работы - это ответственность MVC.
public void AcceptsTypeFilterJson_RequestHeaderAcceptsJson_ReturnsJson()
{
var context = new ActionExecutedContext();
context.HttpContext = // mock an http context and set the accept-type. I don't know how to do this, but there are many questions about it.
context.Result = new ViewResult(...); // What your controller would return
var filter = new AcceptTypesAttribute(HttpContentTypes.Json);
filter.OnActionExecuted(context);
Assert.True(context.Result is JsonResult);
}
Ответ 2
Я просто наткнулся на этот пост в блоге, который кажется правильным для меня, он использует Moq
Edit
Хорошо, так что этот парень делает, издеваясь над HTTPContext
, но также нам нужно настроить ContentType в запросе:
// Mock out the context to run the action filter.
var request = new Mock<HttpRequestBase>();
request.SetupGet(r => r.ContentType).Returns("application/json");
var httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.Request).Returns(request.Object);
var routeData = new RouteData(); //
routeData.Values.Add("employeeId", "123");
var actionExecutedContext = new Mock<ActionExecutedContext>();
actionExecutedContext.SetupGet(r => r.RouteData).Returns(routeData);
actionExecutedContext.SetupGet(c => c.HttpContext).Returns(httpContext.Object);
var filter = new EmployeeGroupRestrictedActionFilterAttribute();
filter.OnActionExecuted(actionExecutedContext.Object);
Примечание. Я сам этого не тестировал.