Thursday, July 23, 2009

Asp.Net MVC Unit Testing Authorization

Asp.Net provides the Authorize attribute for checking to make sure you have an authenticated user and that they are in the correct role(s). Since this is part of the framework, I don’t need to test the attribute (that’s Microsoft’s job). I do want to test that I have applied the attribute with the correct properties.

Here’s my unit test code for checking that the attribute has been applied.

[TestMethod()]
public void Autorization_Attributes_Have_Been_Applied()
{

MethodInfo[] methodInfos = typeof(CustomersController).GetMethods(BindingFlags.Public |
BindingFlags.Static);

foreach (MethodInfo methodInfo in methodInfos)
{
ParameterInfo[] parmInfo = methodInfo.GetParameters();
if (methodInfo.Name == "Create" | methodInfo.Name == "Edit")
{
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
Assert.IsNotNull(attributes);
Assert.AreEqual(1, attributes.Length);
var authorizeAttribute = (AuthorizeAttribute)attributes[0];
Assert.IsTrue(authorizeAttribute.Roles.Contains(ApplicationRoles.ChangeCustomersGroup));
}

if (methodInfo.Name == "Index")
{
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
Assert.IsNotNull(attributes);
Assert.AreEqual(1, attributes.Length);
var authorizeAttribute = (AuthorizeAttribute)attributes[0];
Assert.IsTrue(authorizeAttribute.Roles.Contains(ApplicationRoles.ViewCustomersGroup));
}
}
}
Depending on how much you need to test, you can make sure that only specific roles are applied, etc. My sample above only checks for the Index, Create and Edit methods and allows all others to fall through. You could make it fail so that any public method that wasn’t checked failed the test. Remember, if it’s public on your controller it can be called.



Update: April 1, 2010 -- Josh has taken this to the next step. Check it out here.

2 comments:

Josh Schramm said...

hey Paul, great post, helped me out a lot. I hope you don't mind but I took your example here and tweaked it a bit. I wrote about it here if your curious - http://joshreedschramm.com/2010/03/unit-testing-role-based-security-w-asp-net-mvc/

Thanks again.

PretzelSteelersFan said...

Thanks Josh. Your stuff looks great and I've added a link in the post so everyone will see it. I'll also be posting some stuff that I've developed for testing around the move to declarative validation.