I recently started to leverage extension methods in my unit tests as a way to create more readable and strongly typed unit tests. Here's an example:

 1 [Test]
 2   public void should_be_able_to_subtract_one_number_from_another() {
 3       var twenty = Number( 20 );
 4       var three = Number( 3 );
 5       var seventeen = Number( 17 );
 6 
 7       var calculator = CreateSUT( );
 8       var resultOfCalculation
 9           = calculator
10               .Number( twenty )
11               .Minus( )
12               .Number( three )
13               .ComputesTo( );
14 
15       resultOfCalculation.ShouldBeEqualTo( seventeen );
16   }

This is a completely state based unit test that asserts that the result of the calculation is equal to 17. The actual assertion actually happens in an extension method. Defined below:

1 public static class AssertionExtensions {
2       public static void ShouldBeEqualTo< T >( this T itemToCheck, T valueToBeEqualTo ) {
3           Assert.AreEqual( valueToBeEqualTo, itemToCheck );
4       }
5   }

MbUnits Assert.AreEqual() method has several overloads. The one I use the most is the overload defined as follows:

1 public void AreEqual( object expected, object actual ) {...}

The problem I have with this overload is that it's not strongly typed. So I could have written an Assertion that looked like:

1 Assert.AreEqual( 17, new Number(17) );

This won't give me a compile error but will indicate a broken test with the following message.

Equal assertion failed: [[17]]!=[[Calculator.Domain.Number]]

This happens because the integer value type 17 is not equal to the Number reference type with an underlying value of 17. Also, this would have boxed the value type to a reference type to use the overload that accepts two objects. (which is also expensive)

By extending the assertion with a generic extension method, I get a more readable test with the strong typing of generics.

Hopefully, this saves you from some embarrassing moments with your pair!

comments powered by Disqus