So I'm creating a custom ActionFilter that's based mostly on this project http://www.codeproject.com/KB/aspnet/aspnet_mvc_restapi.aspx.
所以我正在创建一个自定义的ActionFilter,它主要基于这个项目http://www.codeproject.com/KB/aspnet/aspnet_mvc_restapi.aspx。
I want a custom action filter that uses the http accept headers to return either JSON or Xml. A typical controller action will look like this:
我想要一个自定义操作过滤器,它使用http接受标头返回JSON或Xml。典型的控制器操作如下所示:
[AcceptVerbs(HttpVerbs.Get)]
[AcceptTypesAttribute(HttpContentTypes.Json, HttpContentTypes.Xml)]
public ActionResult Index()
{
var articles = Service.GetRecentArticles();
return View(articles);
}
The custom filter overrides the OnActionExecuted and will serialize the object (in this example articles) as either JSON or Xml.
自定义筛选器会覆盖OnActionExecuted,并将对象(在此示例文章中)序列化为JSON或Xml。
My question is: how do I test this?
我的问题是:我该如何测试?
- What tests do I write? I'm a TDD novice and am not 100% sure what I should be testing and what not to test. I came up with
AcceptsTypeFilterJson_RequestHeaderAcceptsJson_ReturnsJson()
,AcceptsTypeFilterXml_RequestHeaderAcceptsXml_ReturnsXml()
andAcceptsTypeFilter_AcceptsHeaderMismatch_ReturnsError406()
. - 我写什么测试?我是TDD新手,并不是100%确定我应该测试什么以及不测试什么。我想出了AcceptsTypeFilterJson_RequestHeaderAcceptsJson_ReturnsJson(),AcceptsTypeFilterXml_RequestHeaderAcceptsXml_ReturnsXml()和AcceptsTypeFilter_AcceptsHeaderMismatch_ReturnsError406()。
- How do I test an ActionFilter in MVC that is testing the Http Accept Headers?
- 如何在MVC中测试正在测试Http Accept Headers的ActionFilter?
Thanks.
谢谢。
2 个解决方案
#1
21
You just need to test the filter itself. Just create an instance and call the OnActionExecuted()
method with test data then check the result. It helps to pull the code apart as much as possible. Here's an example I've written. Most of the heavy lifting is done inside the CsvResult
class which can be tested individually. You don't need to test the filter on an actual controller. Making that work is the MVC framework's responsibility.
您只需要测试过滤器本身。只需创建一个实例并使用测试数据调用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
10
I just stumbled upon this blog post which seems the right way to me, he uses Moq
我偶然发现了这篇博文,这对我来说似乎是正确的方式,他使用的是Moq
Edit
编辑
Okay so what this chap is doing is mocking the HTTPContext
, but also we need to setup a ContentType in the request:
好的,这个小伙子正在做的是模拟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);
Note - I have not tested this myself
注意 - 我自己没有测试过
#1
21
You just need to test the filter itself. Just create an instance and call the OnActionExecuted()
method with test data then check the result. It helps to pull the code apart as much as possible. Here's an example I've written. Most of the heavy lifting is done inside the CsvResult
class which can be tested individually. You don't need to test the filter on an actual controller. Making that work is the MVC framework's responsibility.
您只需要测试过滤器本身。只需创建一个实例并使用测试数据调用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
10
I just stumbled upon this blog post which seems the right way to me, he uses Moq
我偶然发现了这篇博文,这对我来说似乎是正确的方式,他使用的是Moq
Edit
编辑
Okay so what this chap is doing is mocking the HTTPContext
, but also we need to setup a ContentType in the request:
好的,这个小伙子正在做的是模拟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);
Note - I have not tested this myself
注意 - 我自己没有测试过