如何在ASP.Net MVC中对自定义ActionFilter进行单元测试

时间:2011-12-14 16:41:54

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

所以我正在创建一个主要基于此项目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. 如何测试正在测试Http Accept Headers的MVC中的ActionFilter?
  3. 感谢。

2 个答案:

答案 0 :(得分:25)

您只需要测试过滤器本身。只需创建一个实例并使用测试数据调用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);
}

答案 1 :(得分:14)

我偶然发现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);

注意 - 我自己没有测试过这个