Asp.net-Mvc

如何用 Moq 模擬 ActionExecutingContext?

  • April 14, 2016

我正在嘗試測試以下過濾器:

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);
           }
       }
   }
}

我正在嘗試使用 Moq 模擬 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(
       Mock.Of<HttpContext>(),
       Mock.Of<RouteData>(),
       Mock.Of<ActionDescriptor>(),
       modelState
   );

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

   validationFilter.OnActionExecuting(actionExecutingContext);

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

引用自:https://stackoverflow.com/questions/36629391