Как выполнить модульное тестирование пользовательского 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.

У меня вопрос: как это проверить?

  1. Какие тесты писать? Я новичок в TDD и не уверен на 100%, что мне следует тестировать, а что нет. Я придумал AcceptsTypeFilterJson_RequestHeaderAcceptsJson_ReturnsJson(), AcceptsTypeFilterXml_RequestHeaderAcceptsXml_ReturnsXml() и AcceptsTypeFilter_AcceptsHeaderMismatch_ReturnsError406().
  2. Как протестировать ActionFilter в MVC, который проверяет заголовки Http Accept?

Спасибо.


person John    schedule 14.12.2011    source источник


Ответы (2)


Вам просто нужно проверить сам фильтр. Просто создайте экземпляр и вызовите метод 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);
}
person Ryan    schedule 14.12.2011
comment
Я не знаю, когда это изменилось, но в .Net Core 3.1 ActionExecutedContext нет конструктора без аргументов, что усложняет настройку. - person E-Riz; 02.11.2020

Я только что наткнулся на это сообщение в блоге, которое кажется правильным способом меня. Он использует Moq.

Этот парень издевается над 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);

Примечание - я не проверял это сам.

person Luke T O'Brien    schedule 10.04.2015