【问题标题】:Unit Testing a custom Web API AuthorizeAttribute对自定义 Web API AuthorizeAttribute 进行单元测试
【发布时间】:2017-06-06 17:09:38
【问题描述】:

我正在尝试使用 C# 中的 NUnit 对自定义授权属性进行单元测试。特别是在未授权的情况下返回了特定的http状态码和消息。

我的属性超级简单——看起来像这样:

public class AuthorizationAttribute : AuthorizeAttribute
{

    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (IsAuthorized(actionContext))
            return;

        HandleUnauthorizedRequest(actionContext);
    }

    protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "You are not authorized to access this resource");
    }
}

所以为了测试这个(目前是测试领域的新手),我拼凑了以下代码。在其中,我附加了一个带有用户名和一些角色数据的通用身份。

public void Given_UserIsNotInAuthorizedRoles_When_Auhtorizing_ReturnsForbidden()
{

    // Arrange

    IPrincipal principal = new GenericPrincipal(new GenericIdentity("TestName"), new[] { "TestRole" });

    HttpActionContext mockActionContext = new HttpActionContext()
    {
        ControllerContext = new HttpControllerContext()
        {
            Request = new HttpRequestMessage(),
            RequestContext = new HttpRequestContext() { Principal = principal }
        },
        ActionArguments = { { "SomeArgument", "null" } }
    };

    mockActionContext.ControllerContext.Configuration = new HttpConfiguration();
    mockActionContext.ControllerContext.Configuration.Formatters.Add(new JsonMediaTypeFormatter());

    // Act
    AuthorizationAttribute authAttr = new AuthorizationAttribute();
    authAttr.OnAuthorization(mockActionContext);

    // Assert
    Assert.IsTrue(mockActionContext.Response.StatusCode == System.Net.HttpStatusCode.Forbidden);

}

模拟控制器如下所示:

[Authorization(Roles = "AdminRoleOnly", Users = "A user")]
internal class MockController : ApiController { }

当我调试时,我发现 if (IsAuthorized(actionContext)) 正在返回 true - 我不明白。

有人可以指出为什么我的授权属性可以很好地传递这个身份吗?

不管怎样,这段代码可以在生产环境中使用。我正在回填一些测试。


有些相关,是这些

我已经通读了关于类似问题ASP.NET MVC unit testing custom AuthorizeAttribute 的问答,尽管它们实际上既不工作也不相关,尤其是考虑到它们是针对 MVC 控制器而不是 Api 控制器的。

我也已阅读并尝试在此问题的答案中实现代码Mocking HttpActionContext.ActionArguments when testing Web.Api ActionFilter


后者让我接近某个地方,因为我的授权属性正在测试中触发,并且我能够传递所需的上下文信息。

【问题讨论】:

  • 您期待哪种行为?如果 (IsAuthorized(actionContext)) 返回 true,这意味着您提供的 mockActionContext 是有效的 :) 知道 IsAuthorized 函数中发生了什么吗?
  • 我希望 IsAuthorized 返回 false。我的原则与模拟控制器 AuthorizeAttribute 有不同的作用。我的原则是 Authenticated,但这是不同的。我正在调用的 IsAuthorized 方法位于 AuthorizeAttribute 的基础上。 MSDN 说它只是表示指定的控件是否被授权。我理解这是基于角色等发生的。
  • 看看IsAuthorized的源代码中发生了什么
  • @Nkosi - 谢谢。那为什么,如果我完全删除该原则,它不会返回错误?它应该在第一个 if 上返回 false
  • @zeroflaw 您可能已经对其进行了排序,但是对于那些遇到相同问题的人-确保上下文中的响应对象不为空:)

标签: c# unit-testing asp.net-web-api nunit


【解决方案1】:

您需要将Role 分配给AuthorizationAttribute。在您的示例中,您有一个 TestRole 分配给委托人。分配除此之外的任何其他角色。

// Act
AuthorizationAttribute authAttr = new AuthorizationAttribute() {
    Roles = "SomeOtherRole"
};

并且测试在执行时应该按预期运行。

如果您查看IAuthorized 的源代码,您将看到检查是否有分配给属性的角色的逻辑。如果没有可比较的,则默认为true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2017-06-02
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多