In setting up a complete set of tests for an ASP.NET MVC application, I have been using MVCFakes to test actions that need to access context objects. This works quite nicely when all the code is inside the action method - just set the context and call the method. It won’t however test anything set up using attributes.

I found posts from Paul Brown and Josh Reed Schramm that come close to what I need, but I want to test that an unauthorized user can’t run the code rather than checking for presence of the attribute directly.

The below method will stop execution if the request is unauthorized and return the result of the action method otherwise. I also made versions for actions with parameters, but haven’t included that code as it isn’t much more than changing the type parameters.

public static ActionResult Invoke(this Controller c, Func f)
    {

        var methodInfo = f.Method;
        var attributes = methodInfo.GetCustomAttributes(
           typeof(AuthorizeAttribute), true);
        if (attributes.Length == 1)
        {
            var aa = attributes[0] as AuthorizeAttribute;
            var user = c.User;
            if (user == null
                || user.Identity == null
                || !user.Identity.IsAuthenticated
                || (!string.IsNullOrEmpty(aa.Roles)
                    && !aa.Roles.Split(',')
                    .Where(r => user.IsInRole(r.Trim()))
                    .Any()))
            {
                return new HttpUnauthorizedResult();
            }
        }

        return f.Invoke();
    }

The method can be called in tests as follows:

var controller=new HomeController();
controller.ControllerContext = new FakeControllerContext(
    controller,
    userid == null ? null : userid.ToString(),
    roles);

var result1 =  controller.Invoke(controller.Index);
Assert.That(result1 is HttpUnauthorizedResult);