【发布时间】: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