【问题标题】:How do I unit test a custom ActionFilter in ASP.Net MVC如何在 ASP.Net MVC 中对自定义 ActionFilter 进行单元测试
【发布时间】:2012-01-20 10:42:57
【问题描述】:

所以我正在创建一个主要基于这个项目http://www.codeproject.com/KB/aspnet/aspnet_mvc_restapi.aspx 的自定义 ActionFilter。

我想要一个自定义操作过滤器,它使用 http 接受标头返回 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. 如何在 MVC 中测试正在测试 Http Accept Headers 的 ActionFilter?

谢谢。

【问题讨论】:

标签: asp.net-mvc unit-testing tdd actionfilterattribute


【解决方案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);
}

【讨论】:

  • 我不知道它什么时候改变的,但是在.Net Core 3.1 ActionExecutedContext 没有无参数构造函数,使得设置更加困难。
【解决方案2】:

我偶然发现了this blog post,这对我来说似乎是正确的方式。他使用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);

注意 - 我自己没有测试过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2020-10-29
    相关资源
    最近更新 更多