7

I have taken a look at:

I am trying to test a custom AuthorizeAttribute that I wrote.

I have tried many different things to get it to work. This is my current attempt.

[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 == ""));
}

No matter what I do I always get a System.NullReferenceException when I run the test. It never seems to get past the OnAuthorization call. The stack trace is as follows:

Result Message: 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

Does anybody have any ideas on how to solve this problem?

Edit

I found the solution. I also needed to mock ControllerDescriptor and make sure that HttpContextBase.Items returned a new Dictionary.

Working code:

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"));
7
  • home/Unauthorized allows anonymous? check in web.config Commented Oct 11, 2013 at 9:17
  • Which line is no. 29? Commented Oct 11, 2013 at 9:21
  • I wouldn't think that would make a difference as I am mocking everything? The site is not deployed anywhere and I am directly calling my Attribute class methods. I removed base.HandleUnauthorizedRequest(filterContext); just in case but I still get the exception. Commented Oct 11, 2013 at 9:26
  • Line 29: configAtt.OnAuthorization(authContext.Object); Commented Oct 11, 2013 at 9:26
  • Then either configAtt or authContext.Object are null. Check you check on that? Commented Oct 11, 2013 at 10:16

1 Answer 1

14

I found the solution. I also needed to mock ControllerDescriptor and make sure that HttpContextBase.Items returned a new Dictionary.

Working code:

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"));
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.