C# 对方法的单元测试角色访问

C# 对方法的单元测试角色访问,c#,asp.net,asp.net-mvc,unit-testing,asp.net-web-api,C#,Asp.net,Asp.net Mvc,Unit Testing,Asp.net Web Api,如何测试WebApi/MVC项目中方法或控制器上的authorize属性是否具有特定角色 所以我可以测试一个方法,做如下的事情 [Test] [TestCase("Put", new []{"Admin","TeamMember"})] [TestCase("Post", new []{"Admin","TeamMember"})] [TestCase("Get", new []{"TeamMember"})] public void Ensure_Me

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

所以我可以测试一个方法,做如下的事情

    [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));
    }
这是否合理,或者我是否应该直接测试控制器操作,并测试响应是否为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;
    }
或者,如果要使测试更严格,并且每个操作只强制一个Authorize属性,请执行以下操作:

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

根据您的代码,我认为您所做的只是测试authorized属性是否有效,这是Microsoft的责任。一个集成测试来断言您得到了一个401/403,这是很好的,但是测试一个控制器的操作可能就足够了。我不同意。我正在测试一个特定的方法是否有一组指定的角色。或者至少这就是我想做的…:)我也想到了。如果您要更改一个方法的角色,这可能是您打算做的事情,您只是需要确保测试现在与更改匹配,从而导致不必要的工作。我看到了在允许的角色周围进行单元测试的价值。当允许的角色发生意外更改时,最好让单元测试失败(并修复)。干杯,将在上午进行测试很好,干杯成功了。我对签名和正文做了一些修改,并将其张贴在我的问题中。
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;
}