如何使用Moq模拟ActionExecutingContext?
问题描述:
我想测试以下过滤器:如何使用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一个过滤器?
答
我只是偶然发现了同样的问题,并以这种方式解决了这个问题。
[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);
}