单元测试自定义验证过滤器 [英] Unit Testing a Custom Validation Filter
问题描述
我有以下属性:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
我有这样的通用扩展方法来确定属性是否被应用于方法还是不
I have this generic extension method for Determining whether the attribute is applied to a method or not
public static bool ActionHasFilter(this ApiController controller, string action, Type filter)
{
var controllerType = controller.GetType();
var method = controllerType.GetMethod(action);
object[] filters = method.GetCustomAttributes(filter, true);
return filters.Any(x=>x.GetType() == filter);
}
我的问题是我如何去测试属性是否实际工作或没有,没有测试控制器动作?
My problem is how do i go about testing whether the attribute actually works or not, without testing the controller action?
让我们说我有以下实体
public class UserViewModel
{
[Required]
public string Name {get; set;}
[Required]
[EmailAddress]
public string Email {get;set;
}
我将如何去嘲讽的背景和检查模型是否有效?
How would i go about mocking the context and checking whether the model is valid?
我使用NUnit和起订量。
I'm using Nunit and Moq.
推荐答案
Spock的解决方案是在正确的轨道上,但是在code有点太侵入,因为它使 ValidateModelAttribute
类依赖于 TestableHttpActionContext
。我的实现使用将用于注入为单元测试的请求
对象的公共财产,而作为属性的实施,继续使用请求
从对象中的 ActionContext中
:
Spock's solution is on the right track, but is a bit too invasive on the code, because it makes the ValidateModelAttribute
class dependent on TestableHttpActionContext
. My implementation uses a public property that will be used to "inject" the Request
object for the Unit Tests, while the implementation as attribute continues to use the Request
object from the ActionContext
:
public class ValidateModelAttribute : ActionFilterAttribute
{
public HttpRequestMessage TestRequestMessage { get; set; }
public override void OnActionExecuting(HttpActionContext actionContext)
{
PerformValidation(actionContext, TestRequestMessage ?? actionContext.Request);
}
private void PerformValidation(HttpActionContext actionContext, HttpRequestMessage request)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response = request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
单元测试:
[Test]
public void OnActionExecuting_ValidModel_ResponseIsNotSet()
{
var actionContext = new HttpActionContext();
actionContext.ModelState.Clear();
var attribute = new ValidateModelAttribute { TestRequestMessage = new HttpRequestMessage() };
attribute.OnActionExecuting(actionContext);
Assert.IsNull(actionContext.Response);
}
[Test]
public void OnActionExecuting_InvalidModel_ResponseIsSetToBadRequest()
{
var actionContext = new HttpActionContext();
actionContext.ModelState.AddModelError("key", "error");
var attribute = new ValidateModelAttribute() { TestRequestMessage = new HttpRequestMessage() };
attribute.OnActionExecuting(actionContext);
Assert.AreEqual(HttpStatusCode.BadRequest, actionContext.Response.StatusCode);
}
请注意,我没有使用的实际模型来验证的ModelState
,因为这是超出范围的单元测试:我们要测试的的ModelState
的结果,而不是的ModelState
本身。 ; - )
Please note that I'm not using an actual model to validate the ModelState
, because that's out of scope for the Unit Tests: We want to test the ModelState
's outcome, not the ModelState
itself. ;-)
这篇关于单元测试自定义验证过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!