Saturday, 26 August 2017

c# - NullReferenceException thrown when testing custom AuthorizationAttribute



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();
user.Setup(u => u.Identity.IsAuthenticated).Returns(false);

var authContext = new Mock();
authContext.Setup(ac => ac.HttpContext.User).Returns(user.Object);

var configAtt = new ConfigurableAuthorizeAttribute();

configAtt.OnAuthorization(authContext.Object);

authContext.Verify(ac => ac.Result == It.Is(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();
context.Setup(c => c.Items).Returns(new Dictionary());

context.Setup(c => c.User.Identity.IsAuthenticated).Returns(false);
var controller = new Mock();

var actionDescriptor = new Mock();
actionDescriptor.Setup(a => a.ActionName).Returns("Index");
var controllerDescriptor = new Mock();
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());
Assert.That(((RedirectResult)filterContext.Result).Url, Is.EqualTo("~/home/Unauthorized"));

Answer



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();
context.Setup(c => c.Items).Returns(new Dictionary());
context.Setup(c => c.User.Identity.IsAuthenticated).Returns(false);
var controller = new Mock();

var actionDescriptor = new Mock();
actionDescriptor.Setup(a => a.ActionName).Returns("Index");
var controllerDescriptor = new Mock();

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());
Assert.That(((RedirectResult)filterContext.Result).Url, Is.EqualTo("~/home/Unauthorized"));


No comments:

Post a Comment

casting - Why wasn't Tobey Maguire in The Amazing Spider-Man? - Movies & TV

In the Spider-Man franchise, Tobey Maguire is an outstanding performer as a Spider-Man and also reprised his role in the sequels Spider-Man...