2016-04-14 105 views
6

我想测试以下过滤器:如何使用Moq模拟ActionExecutingContext?

using Microsoft.AspNet.Mvc; 
using Microsoft.AspNet.Mvc.Filters; 

namespace Hello 
{ 
    public class ValidationFilter : ActionFilterAttribute 
    { 
     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      if (!filterContext.ModelState.IsValid) { 
       filterContext.Result = new BadRequestObjectResult(filterContext.ModelState); 
      } 
     } 
    } 
} 

我试图嘲弄ActionFilterAttribute使用起订量。

我使用MVC 6.0.0-RC1

我第一次尝试:

var context = new ActionExecutingContext(
        new ActionContext(Mock.Of<HttpContext>(), new RouteData(), new ActionDescriptor()), 
        new IFilterMetadata[] { filter, }, 
        new Dictionary<string, object>(), 
        controller: new object()); 

但我不能覆盖的ModelState。它看起来是只读:https://github.com/aspnet/Mvc/blob/6.0.0-rc1/src/Microsoft.AspNet.Mvc.Abstractions/ActionContext.cs#L25

然后我尝试:

var contextMock = new Mock<ActionExecutingContext>(
        new ActionContext(Mock.Of<HttpContext>(), new RouteData(), new ActionDescriptor()), 
        new IFilterMetadata[] { filter, }, 
        new Dictionary<string, object>()); 

但是,当我打电话filter.OnActionExecuting(contextMock.Object)我得到以下错误:

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: Microsoft.AspNet.Mvc.Filters.ActionExecutingContext. 
     Could not find a constructor that would match given arguments: 
     Microsoft.AspNet.Mvc.ActionContext 
     Microsoft.AspNet.Mvc.Filters.IFilterMetadata[] 
     System.Collections.Generic.Dictionary`2[System.String,System.Object] 

如何测试使用的ModelState一个过滤器?

回答

9

我只是偶然发现了同样的问题,并以这种方式解决了这个问题。

[Fact] 
public void ValidateModelAttributes_SetsResultToBadRequest_IfModelIsInvalid() 
{ 
    var validationFilter = new ValidationFilter(); 
    var modelState = new ModelStateDictionary(); 
    modelState.AddModelError("name", "invalid"); 

    var actionContext = new ActionContext(
     new Mock<HttpContext>().Object, 
     new Mock<RouteData>().Object, 
     new Mock<ActionDescriptor>().Object, 
     modelState 
    ); 

    var actionExecutingContext = new ActionExecutingContext(
     actionContext, 
     new List<IFilterMetadata>(), 
     new Dictionary<string, object>(), 
     new Mock<Controller>().Object 
    ); 

    validatationFilter.OnActionExecuting(actionExecutingContext); 

    Assert.IsType<BadRequestObjectResult>(actionExecutingContext.Result); 
}