1
votes

This question is pretty much a duplicate of ASP.NET MVC unit testing custom AuthorizeAttribute - however I cannot get my code to run without hitting the same NullReferenceException

Something is clearly missing when I mock up my controller.

My attribute is simple - looks like this:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    if (!base.AuthorizeCore(filterContext.HttpContext))
    {
        filterContext.Controller.TempData.Add("RedirectReason", "Unauthorized");
    }
    base.OnAuthorization(filterContext);
}

My most recent attempt is below. I also tried the code from the question on that referenced link, including adding items to the context.

 // Arrange
        Mock<IPrincipal> userMock = new Mock<IPrincipal>();
        Mock<HttpResponseBase> responseMock = new Mock<HttpResponseBase>();
        responseMock.SetupGet(res => res.Cache).Returns(new Mock<HttpCachePolicyBase>().Object);

        Mock<HttpContextBase> contextMock = new Mock<HttpContextBase>(MockBehavior.Strict);
        contextMock.SetupGet(cm => cm.User).Returns(userMock.Object);
        contextMock.SetupGet(cm => cm.Response).Returns(responseMock.Object);
        contextMock.SetupGet(cm => cm.Items).Returns(new Mock<IDictionary>().Object);

        Mock<ControllerContext> controllerContextMock = new Mock<ControllerContext>();
        controllerContextMock.SetupGet(ctx => ctx.HttpContext).Returns(contextMock.Object);

        Mock<ActionDescriptor> actionDesMock = new Mock<ActionDescriptor>();
        actionDesMock.Setup(action => action.GetCustomAttributes(typeof(AllowAnonymousAttribute), true)).Returns(new object[0]);

        // Act
        CustomAuthorizationAttribute cusAtr = new CustomAuthorizationAttribute() { Roles = "TestRole" };

        // Assert
        cusAtr.OnAuthorization(new AuthorizationContext(controllerContextMock.Object, actionDesMock.Object));

I've also checked out the source code for AuthorizeCore.

When ran, the test fails on base.AuthorizeCore(filterContext.HttpContext) with a NullReferenceException

Can't figure what's missing.

any idea?


For the sake of ease, code from the other question, adjusted to suit our models is:

    // Arrange
    var httpContext = new Mock<HttpContextBase>();
    Dictionary<object, object> dictionary = new Dictionary<object, object>();
    httpContext.SetupGet(cm => cm.Items).Returns(dictionary);
    Mock<IPrincipal> userMock = new Mock<IPrincipal>();
    httpContext.SetupGet(c => c.User).Returns(() => userMock.Object); 
    var requestBase = new Mock<HttpRequestBase>();
    var headers = new NameValueCollection
    {
       {"Special-Header-Name", "false"}
    };
    requestBase.Setup(x => x.Headers).Returns(headers);
    requestBase.Setup(x => x.HttpMethod).Returns("GET");
    requestBase.Setup(x => x.Url).Returns(new Uri("http://localhost/"));
    requestBase.Setup(x => x.RawUrl).Returns("~/Maintenance/UnExistingMaster");
    requestBase.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(() => "~/Maintenance/UnExistingMaster");
    requestBase.Setup(x => x.IsAuthenticated).Returns(() => true);
    httpContext.Setup(x => x.Request).Returns(requestBase.Object);
    var controller = new Mock<ControllerBase>();
    var actionDescriptor = new Mock<ActionDescriptor>();
    var controllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller.Object);

    CustomAuthorizationAttribute cusAtr = new CustomAuthorizationAttribute() { Roles = "TestRole" };

    // Act
    cusAtr.OnAuthorization(new AuthorizationContext(controllerContext, actionDescriptor.Object));
1
provide a minimal reproducible example that can be used to reproduce the problem. Help us to help you. Having to go check another question to try and piece together your attribute for testing makes helping that more difficult. Do not assume that we already have a background with the linked question. Identify exactly where you get the error. The question should be able to stand on its own. - Nkosi
@Nkosi - Would you mind letting me know what I am missing? I have provided every piece of code I have for this issue, along with what issue I am experiencing. Not sure what else I can add? The attribute is at the top of the question. My test is at the bottom. I reference the other question so reads know there is a possible duplicate; rather than have users attempt to close the Q based on a duplicate - Darren Wainwright

1 Answers

1
votes

You referenced the source code. Have you taken a look at what it needs and what you have setup? You set a principal mock. great. but the identity is not set. in checking user is calls

if (!user.Identity.IsAuthenticated) //<-- Identity would be null.

Which will null out because an Identity was not arranged.

Just create a generic principal and use that. All the necessary dependencies would be initialized for you.

//...

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

httpContext.SetupGet(c => c.User).Returns(() => principal);

//...

This will get you past your initial hurdle. You may still have to review your arrangement for any other dependencies that were not arranged properly.