Thomas Ardal

Freelance software consultant and entrepreneur building SaaS applications like elmah.io

Unit testing attribute decorations

This is my first blog post about unit testing. And so, without further ado here’s a small utility I wrote the other day.

Problem

Attributes in .NET as well as annotations in Java are great. I simply love the strengths of action filters in ASP.NET MVC, which are simply just a way to do aspect oriented programming through attributes. You typically want to write a unit test of the method annotated with an attribute, as well as a unit test of the attribute implementation. But sometimes it would be a disaster if someone by mistake removed or out commented the attribute definition from a method. So why not write a unit test of the presence of the attribute? In my case I had a number of ASP.NET MVC actions, annotated with the Authorize attribute. This simply tells the framework to verify that only logged on users can call the method.

Solution

My solution was to write some reflection code, which verifies the presence of a specified attribute on the method under test. I’m a big fan of DRY and therefore wanted to make a reusable method for this scenario. Inspired by Shoudly (a framework for writing cleaner unit tests, which I will probably write more about in the future), I wrote the following extension method:

public static void ShouldHave<T, TT>(this T obj, Expression<Func<T, TT>> exp, params Type[] attributes)
{
    var memberExpression = exp.Body as MethodCallExpression;
    foreach (var attribute in attributes)
    {
        Assert.That(
            memberExpression.Method.GetCustomAttributes(attribute, false).Any(),
            Is.True,
            attribute.Name + " not found on " + memberExpression.Method.Name);
    }
}

This small method makes unit testing the presence of an attribute piece of pie:

var controller = new HomeController();
controller.ShouldHave(x => x.Index(), typeof(AuthorizeAttribute));

Nice! We now have a strongly typed test, which verifies the AuthorizeAttribute on the Index method.

Show Comments