单元测试角色对方法的访问权限

本文关键字:访问 访问权 权限 方法 角色 单元测试 | 更新日期: 2023-09-27 18:31:48

我将如何测试 WebApi/MVC 项目中方法或控制器上的授权属性是否具有特定角色

所以我可以测试一个像下面这样做的方法吗?

    [Test]
    [TestCase("Put", new []{"Admin","TeamMember"})]
    [TestCase("Post", new []{"Admin","TeamMember"})]
    [TestCase("Get", new []{"TeamMember"})]
    public void Ensure_Methods_have_Correct_Roles(string methodToTest, List<string> roles)
    {
        var controller = new myController();
        Assert.IsTrue(controller.HasRoles(methodToTest, roles));
    }

像这样存根具有角色扩展方法

    public static bool HasRoles(this Controller controller, string action, string[] roles)
    {
        var controllerType = controller.GetType();
        var method = controllerType.GetMethod(action);
        object[] filters = method.GetCustomAttributes(typeof(AuthorizationAttribute), true);
        if(!filters.Any(x => x.GetType() == typeof(AuthorizationAttribute))
        {
            throw exception()
        }
        var rolesOnCurrentMethodsAttribute = // This is where i'm stuck
        foreach(var role in rolesOnCurrentMethodsAttribute)
        {
           //pseudo-code
           if(!roles.contains(role)
           {
               return false;
           }
        }
        return true;
    }

这是否合理,或者我应该直接测试控制器操作并测试响应是否为 401/403?不过,这需要模拟上下文,并且意味着更多的测试代码,因为我必须单独测试每个方法。

编辑:也许不要关注它是否明智。只是可行吗?

我的想法是,单元测试将是哪些操作应该具有哪些角色的规范规范(因为目前没有书面规范,并且可能永远不会有)。如果开发人员更改了角色,那么他们需要有一个充分的理由。

编辑#2

根据下面的 Con 答案,这就是我最终得到的,一种方法用于检查 aan 操作,另一种用于检查控制器。

 public static bool WebApiActionHasRoles(this ApiController controller, string action, string roles)
    {
        var controllerType = controller.GetType();
        var method = controllerType.GetMethod(action);
        object[] filters = method.GetCustomAttributes(typeof(System.Web.Http.AuthorizeAttribute), true);
        if (!filters.Any())
        {
            throw new Exception();
        }
        var rolesOnCurrentMethodsAttribute = filters.SelectMany(attrib => ((System.Web.Http.AuthorizeAttribute)attrib).Roles.Split(new[] { ',' })).ToList();
        var rolesToCheckAgainst = roles.Split(',').ToList();
        return !rolesOnCurrentMethodsAttribute.Except(rolesToCheckAgainst).Any() && !rolesToCheckAgainst.Except(rolesOnCurrentMethodsAttribute).Any();
    }
    public static bool WebApiControllerHasRoles(this ApiController controller, string roles)
    {
        var controllerType = controller.GetType();

        object[] filters = controllerType.GetCustomAttributes(typeof(System.Web.Http.AuthorizeAttribute), true);
        if (!filters.Any())
        {
            throw new Exception();
        }
        var rolesOnCurrentMethodsAttribute = filters.SelectMany(attrib => ((System.Web.Http.AuthorizeAttribute)attrib).Roles.Split(new[] { ',' })).ToList();
        var rolesToCheckAgainst = roles.Split(',').ToList();
        return !rolesOnCurrentMethodsAttribute.Except(rolesToCheckAgainst).Any() && !rolesToCheckAgainst.Except(rolesOnCurrentMethodsAttribute).Any();
    }

如果要将其与 MVC 而不是 Web API 控制器/操作一起使用,只需将System.Web.Http.AuthorizeAttribute更改为 System.Web.MVC.AuthorizeAttribute,并在方法签名中将ApiController更改为Controller

单元测试角色对方法的访问权限

如果您指的是 AuthorizeAttribute vs AuthorizationAttribute ,这是您需要的吗:

    public static bool HasRoles(this Controller controller, string action, string[] roles)
    {
        var controllerType = controller.GetType();
        var method = controllerType.GetMethod(action);
        object[] filters = method.GetCustomAttributes(typeof(AuthorizeAttribute), true);
        if(!filters.Any())
        {
            throw new Exception();
        }
        var rolesOnCurrentMethodsAttribute = filters.SelectMany(attrib => ((AuthorizeAttribute)attrib).Roles.Split(new[] { ',' })).ToList();
        return roles.Except(rolesInMethod).Count() == 0 && rolesInMethod.Except(roles).Count() == 0;
    }

或者,如果要使测试更严格,并且每个操作仅强制实施一个授权属性:

public static bool HasRoles(this Controller controller, string action, string roles)
{
    var controllerType = controller.GetType();
    var method = controllerType.GetMethod(action);
    var attrib = method.GetCustomAttributes(typeof(AuthorizeAttribute), true).FirstOrDefault() as AuthorizeAttribute;
    if (attrib == null)
    {
        throw new Exception();
    }
    return attrib.Roles == roles;
}