在测试自定义授权属性时引发了NullReferenceException异常

7
我查看了以下内容: 我正在尝试测试我编写的自定义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 : Object reference not set to an instance of an object. Result StackTrace: at System.Web.Mvc.OutputCacheAttribute.GetChildActionFilterFinishCallback(ControllerContext controllerContext) at System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) at ...ConfigurableAuthorizeAttributeTests.unauthenticated_user_not_allowed_to_access_resource() in ...ConfigurableAuthorizeAttributeTests.cs:line 29”
有人有任何想法如何解决这个问题吗?
编辑
我找到了解决方法。我还需要模拟ControllerDescriptor并确保HttpContextBase.Items返回一个新的Dictionary。
工作代码:
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 中检查。 - Murali Murugesan
第29行是哪一行? - Henk Mollema
我认为这不会有任何影响,因为我正在模拟一切?该网站未部署在任何地方,我直接调用我的Attribute类方法。我已经删除了base.HandleUnauthorizedRequest(filterContext);以防万一,但我仍然收到异常。 - pkidza
第29行:configAtt.OnAuthorization(authContext.Object); - pkidza
@HenkMollema 我找到了答案。首先,我必须确保HttpContextBase返回Dictionary的一个新实例。这样就解决了异常问题,但是我还是遇到了另一个NullReferenceException。然后我发现我需要模拟ControllerDescriptor。 - pkidza
显示剩余2条评论
1个回答

13

我找到了解决方案。我还需要模拟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"));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接