Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Unit Testing C# Custom Attributes with NUnit

5.00/5 (1 vote)
25 Jul 2011CPOL2 min read 42.8K  
A simple generic way to test Custom Attributes with NUnit.

I've been experimenting with TDD and as usual I seemed to pick a non-standard problem to start with. In this case, I was creating a new C# Custom Attribute class, e.g.:

C#
public class FunkyAttribute : Attribute
{
 public int SettingOne { get; set; }
 public string Name { get; set; }
}

which would be used like:

C#
[Funky(Name="SomeThingFunkierThanJust_f")]
public static int f() { return 7; }

Testing this is a little strange as rather than having a standard test method which invokes a method and asserts the result, e.g.:

C#
[Test]
public void TestThat_f_Returns7()
{
 Assert.AreEqual(7, SomeClass.f());
}

there is no method to call because an Attribute is applied to an element of the program such as the definition of f() above. In the end, I settled on the following:

C#
public class FunkyTester
{
 [Test]
 [Funky(Name="RipSnorter")]
 public void TestThatNameIsRipSnorter()
 {
  TestAttrProperty<FunkyAttribute, string>(new StackFrame().GetMethod(), 
               "Name", "RipSnorter");
 }

 [Test]
 [Funky(SettingOne=77)]
 public  void TestThatSettingOneIs77()
 {
  TestAttrProperty<FunkyAttribute, int>(new StackFrame().GetMethod(), 
                      "SettingOne", 77);
 }

 // Helpers
 private void TestAttrProperty<TAttr, TProp>(MethodBase method, 
              string argName, TProp expectedValue)
 {
  object[] customAttributes = method.GetCustomAttributes(typeof(TAttr), false);

  Assert.AreEqual(1, customAttributes.Count());

  TAttr attr = (TAttr)customAttributes[0];

  PropertyInfo propertyInfo = attr.GetType().GetProperty(argName);

  Assert.IsNotNull(propertyInfo);
  Assert.AreEqual(typeof (TProp), propertyInfo.PropertyType);
  Assert.IsTrue(propertyInfo.CanRead);
  Assert.IsTrue(propertyInfo.CanWrite);
  Assert.AreEqual(expectedValue, (TProp)propertyInfo.GetValue(attr, null));
 }
}

This test class contains two test methods which are identified by the NUnit [Test] attribute. In addition, there is the use of the FunkyAttribute to be tested, i.e. [Funky]. The Custom Attribute is fairly simple with a default (parameterless) constructor and just two differently typed properties both with a getter and a setter. For each of these, I wanted to check:

  • A Custom Attribute of the correct type existed on the test method.
  • That the property to be tested of the Custom Attribute had the expected name.
  • That the property to be tested of the Custom Attribute had the correct type.
  • That the value of the property to be tested of the Custom Attribute could be set.
  • That the value of the property to be tested of the Custom Attribute could be obtained.
  • That the property to be tested of the Custom Attribute had the expected value.

As I wanted to perform these tests for each property of the Custom Attribute, a helper method was called, which in this case is TestAttrProperty. This method is generic so can be used for any property of a Custom Attribute that has a public getter and setter. It just takes a reference to an instance of the method (which will always be a Test method) that the Custom Attribute is set on along with parameters for the property's name and its expected value. The latter is a generic typed parameter (TProp) along with the type of the actual Custom Attribute (TAttr).

TestAttrProperty() then obtains all the Custom Attribute instances matching the type of TAttr. There can only be zero or one; the success case being one! By limiting the search to just the Custom Attribute type being tested, this means that the NUnit TestAttribute instance is not included, which means no filtering of the results is required prior to the tests. Following that, Reflection is used to obtain the PropertyInfo of the property under test. This is then used for executing the remaining of the tests.

The MethodInfo for the test method is easily obtained from the current stack frame from the System.Diagnostics namespace.

Hopefully this little snippet shows a simple generic way to test Custom Attributes with NUnit.

A next step would be to add the ability to test that the Custom Attribute can be successfully applied to data members.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)