【问题标题】:How to unit test ActionFilterAttribute如何对 ActionFilterAttribute 进行单元测试
【发布时间】:2018-02-20 02:56:42
【问题描述】:

我正在寻找在 .NET Core 2.0 API 项目中测试 ActionFilterAttribute 并想知道最好的方法。请注意,我不是试图通过控制器操作来测试它,只是测试 ActionFilterAttribute 本身。

我该如何进行测试:

    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {
                context.Result = new BadRequestObjectResult(context.ModelState);
            }
        }
    }

【问题讨论】:

    标签: unit-testing .net-core xunit xunit.net actionfilterattribute


    【解决方案1】:

    创建上下文的实例,将其传递给过滤器并断言预期的行为

    例如

    [TestClass]
    public class ValidateModelAttributeTest {
        [TestMethod]
        public void Invalid_ModelState_Should_Return_BadRequestObjectResult() {
            //Arrange
            var modelState = new ModelStateDictionary();
            modelState.AddModelError("", "error");
            var httpContext = new DefaultHttpContext();
            var context = new ActionExecutingContext(
                new ActionContext(
                    httpContext: httpContext,
                    routeData: new RouteData(),
                    actionDescriptor: new ActionDescriptor(),
                    modelState: modelState
                ),
                new List<IFilterMetadata>(),
                new Dictionary<string, object>(),
                new Mock<Controller>().Object);
    
            var sut = new ValidateModelAttribute();
    
            //Act
            sut.OnActionExecuting(context);
    
            //Assert
            context.Result.Should().NotBeNull()
                .And.BeOfType<BadRequestObjectResult>();
        }
    } 
    

    【讨论】:

    • 感谢您的回复。在接受了帮助后发现了这个:stackoverflow.com/questions/36629391/…
    • @nkosi 快速问:当我尝试上面的代码时,ModelState 是有效的。有没有技巧可以让 modelState 处于无效状态?我们是否需要创建一些虚假的路线之类的?
    • @Pure.Krome 您需要在模型状态字典中添加模型错误以使其无效。
    • 我只返回“null”,有什么建议吗?
    • @FrankR.Haugen 你的哪一部分是空的
    【解决方案2】:

    这是一个真实的例子,我还可以访问 action filter 属性中的方法信息和参数:

    假设我有一个带有 ActionAttribute 的控制器方法,如下所示:

     public class HomeController : Controller
        {
        ...
        [FeatureFlagActionAtrribute("user", new String[] { "Feature1" })]
        public IActionResult DoSomethingWithFilterAction(String user)
            {...}
        }
    

    http 调用是这样的:

    /Home/DoSomethingWithFilterAction?user="user1"

    现在,我想在这样的上下文中测试 ActionAttribute FeatureFlagActionAtrribute。

    如果您将上述建议应用于此示例,它看起来像这样(至少对我有用)

     var methodInfoDoSomethingWithFilterAction = typeof(HomeController).GetMethod(nameof(HomeController.DoSomethingWithFilterAction));
        var httpContext = new DefaultHttpContext();
        var routeData = new RouteData();
        FeatureFlagActionAtrribute FeatureFlagActionAtrributeFilter = methodInfoDoSomethingWithFilterAction.GetCustomAttribute<FeatureFlagActionAtrribute>();
        ActionDescriptor actionDescriptor = new ControllerActionDescriptor()
                    {
                        ActionName = methodInfoDoSomethingWithFilterAction.Name,
                        ControllerName = typeof(FeatureFlagTest).Name,
                        DisplayName = methodInfoDoSomethingWithFilterAction.Name,
                        MethodInfo = methodInfoDoSomethingWithFilterAction,
                    };
    
        ActionContext actionContext = new ActionContext(httpContext, routeData, actionDescriptor) ;
        var homeController = new HomeController();
        var attribute = new FeatureFlagActionAtrribute("user", new string[] { "feature1" });
        IDictionary<string, object> actionArguments = new Dictionary<string, object>
                    {
                        ["user"] = "user1"
                    };
    
        var filterMetadata = new List<IFilterMetadata>() { featureFlagActionAtrributeFilter };
    
        ActionExecutingContext actionExecutedContext = new 
        ActionExecutingContext(actionContext, filterMetadata, actionArguments, homeController);
    
    
        attribute.OnActionExecuting(actionExecutedContext);
    

    然后在ActionFilterAttribute里面:

    public override void OnActionExecuting(ActionExecutingContext context)
    {
            ControllerActionDescriptor actionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
            Debug.Print($"2. @Before Method called {actionDescriptor.ControllerName}Controller.{actionDescriptor.ActionName}");
            var controllerName = actionDescriptor.ControllerName;
            var actionName = actionDescriptor.ActionName;
            IDictionary<object, object> properties = actionDescriptor.Properties;
            ParameterInfo[] paramsOfMethod = actionDescriptor.MethodInfo.GetParameters();
            var fullName = actionDescriptor.DisplayName;
    
            var paramNameForKeyOfFeature = ParamNameForKeyOfFeature;
    
            var arguments = context.ActionArguments;
    

    【讨论】:

      猜你喜欢
      • 2012-01-08
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      • 2013-09-30
      • 2019-01-05
      • 2011-03-16
      • 2013-01-02
      相关资源
      最近更新 更多