【发布时间】:2013-10-19 07:25:42
【问题描述】:
我看过了:
- How do I make a unit test to test a method that checks request headers?
- How to mock Controller.User using moq
- How do I unit test a controller method that has the [Authorize] attribute applied?
我正在尝试测试我编写的自定义 AuthorizeAttribute。
我尝试了许多不同的方法来让它发挥作用。这是我目前的尝试。
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class ConfigurableAuthorizeAttribute : AuthorizeAttribute
{
private Logger log = new Logger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private IRoleHelper roleHelper;
public ConfigurableAuthorizeAttribute()
{
roleHelper = new ADRoleHelper();
}
public ConfigurableAuthorizeAttribute(IRoleHelper roleHelper)
{
this.roleHelper = roleHelper;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (!httpContext.User.Identity.IsAuthenticated)
{
return false;
}
if (this.roleHelper.IsUserInRole(this.Roles, HttpContext.Current.User.Identity.Name))
{
return true;
}
return false;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
base.HandleUnauthorizedRequest(filterContext);
filterContext.Result = new RedirectResult("~/home/Unauthorized");
}
}
[Test]
public void unauthenticated_user_not_allowed_to_access_resource()
{
var user = new Mock<IPrincipal>();
user.Setup(u => u.Identity.IsAuthenticated).Returns(false);
var authContext = new Mock<AuthorizationContext>();
authContext.Setup(ac => ac.HttpContext.User).Returns(user.Object);
var configAtt = new ConfigurableAuthorizeAttribute();
configAtt.OnAuthorization(authContext.Object);
authContext.Verify(ac => ac.Result == It.Is<RedirectResult>(r => r.Url == ""));
}
无论我做什么,我在运行测试时总是会收到 System.NullReferenceException。它似乎永远无法通过 OnAuthorization 调用。堆栈跟踪如下:
结果消息:System.NullReferenceException:对象引用不 设置为对象的实例。结果堆栈跟踪:在 System.Web.Mvc.OutputCacheAttribute.GetChildActionFilterFinishCallback(ControllerContext 控制器上下文)在 System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext 过滤器上下文)在 ...ConfigurableAuthorizeAttributeTests.unauthenticated_user_not_allowed_to_access_resource() 在 ...ConfigurableAuthorizeAttributeTests.cs:line 29
有人对如何解决这个问题有任何想法吗?
编辑
我找到了解决方案。我还需要模拟 ControllerDescriptor 并确保 HttpContextBase.Items 返回一个新的字典。
工作代码:
var context = new Mock<HttpContextBase>();
context.Setup(c => c.Items).Returns(new Dictionary<object, object>());
context.Setup(c => c.User.Identity.IsAuthenticated).Returns(false);
var controller = new Mock<ControllerBase>();
var actionDescriptor = new Mock<ActionDescriptor>();
actionDescriptor.Setup(a => a.ActionName).Returns("Index");
var controllerDescriptor = new Mock<ControllerDescriptor>();
actionDescriptor.Setup(a => a.ControllerDescriptor).Returns(controllerDescriptor.Object);
var controllerContext = new ControllerContext(context.Object, new RouteData(), controller.Object);
var filterContext = new AuthorizationContext(controllerContext, actionDescriptor.Object);
var att = new ConfigurableAuthorizeAttribute();
att.OnAuthorization(filterContext);
Assert.That(filterContext.Result, Is.InstanceOf<RedirectResult>());
Assert.That(((RedirectResult)filterContext.Result).Url, Is.EqualTo("~/home/Unauthorized"));
【问题讨论】:
-
home/Unauthorized允许匿名吗?签入 web.config -
哪一行不是。 29?
-
我不认为这会有所作为,因为我在嘲笑一切?该站点未部署在任何地方,我直接调用我的 Attribute 类方法。我删除了 base.HandleUnauthorizedRequest(filterContext);以防万一,但我仍然遇到异常。
-
第 29 行:configAtt.OnAuthorization(authContext.Object);
-
那么
configAtt或authContext.Object为空。检查你检查吗?
标签: c# asp.net-mvc unit-testing nunit moq