Friday, May 25, 2007
Sunday, May 20, 2007
Wednesday, May 02, 2007
When you start to write a substantial number of unit tests, you may discover that your tests have quite a bit in common. For instance, if you have a CreditCard class, you may have a block of code like this in each of your tests:
Assert.AreEqual( expectedCard.Number, actualCard.Number );
Assert.AreEqual( expectedCard.FirstName, actualCard.FirstName );
Assert.AreEqual( expectedCard.MiddleName, actualCard.MiddleName );
Assert.AreEqual( expectedCard.LastName, actualCard.LastName );
Assert.AreEqual( expectedCard.ExpMonth, actualCard.ExpMonth );
Assert.AreEqual( expectedCard.ExpYear, actualCard.ExpYear );
Of course, it won't be exactly the same in each test, and that just amplifies the problem. What happens when you want to add a variable to CreditCard? Copy, paste, paste, paste... and inevitably, miss one. One way to manage this complexity is to implement a custom Equals() method in your class. With that in place, you can collapse the previous code into this:
Assert.AreEqual( expectedCard, actualCard );
Sure enough, this reduces the amount of code in your unit tests and makes them less error-prone. However, if the equality test fails, you will know that one of the credit card's values is incorrect, but you won't know which. You can probably figure that out with a little debugging, but I prefer tests to be more explicit when they fail. So to deal with this, I'll typically create a test utility class for each class that looks something like this:
public class CreditCardUtil
public static void AssertAreEqual( CreditCard expected, CreditCard actual )
Assert.AreEqual( expected.Number, actual.Number );
Assert.AreEqual( expected.FirstName, actual.FirstName );
Assert.AreEqual( expected.MiddleName, actual.MiddleName );
Assert.AreEqual( expected.LastName, actual.LastName );
Assert.AreEqual( expected.ExpMonth, actual.ExpMonth );
Assert.AreEqual( expected.ExpYear, actual.ExpYear );
This way, the unit test code is just as simple, but you get meaningful error messages when the test fails. This pattern is useful when you're working on a TDD project with a group, because each person on the team will know where to look if they need a particular bit of functionality. Looking for a method that will compare two Invoices? Try InvoiceUtil.AssertAreEqual. Not there? Write it.
You may want to extend these utility classes to do other useful things, such as:
- Instance an object that is initialized with unique properties (useful for comparison)
- Perform CRUD database operations
- Setup all of the object's dependencies
- Define useful constants, file paths, etc. specific to the object
- Find a similar test
- Copy it
- Change it a little
Tuesday, May 01, 2007
Oren Eini (aka Ayende Rahien) just released the latest version of Rhino Mocks, v3.0.5. This release includes a great new syntax for record and replay that will make your tests much easier to follow. Check out the syntactic sweetness here, be impressed, then download it here.
Thursday, April 26, 2007
When writing unit tests, I frequently find myself wanting to test private methods. I used to think there were only three approaches to solving this problem.
- Test the private method indirectly through some other, public method that invokes it.
- Pros: Keeps your class interface clean and doesn't compromise your OO design
- Cons: You may not be able to test all of the cases you'd like through the public method, and your test results may be affected by the code in the public method.
- Pros: Allows you test the method directly
- Cons: Compromises the encapsulation of your initial design, requires writing more test classes.
- Pros: Doesn't require more test code, you may actually end up with more well-factored design
- Cons: You probably don't want to make this code public, isn't that why it was private in the first place?
- Use reflection to invoke the private method directly
- Pros: Totally rocks.
- Cons: Invoking the private method looks a little funky
public class TestReflector
public static T InvokeNonPublicMethod<T>( string methodName, object obj,
params object parameters )
MethodInfo methodInfo =
obj.GetType().GetMethod( methodName, BindingFlags.NonPublic |
if ( methodInfo == null )
throw new ApplicationException( "Private method not found for: '" +
methodName + "'." );
return (T)methodInfo.Invoke( obj, parameters );
With that in place, it's very simple to use:
MyClass myClass = new MyClass();
string string1 = "abcdef";
string string2 = "123456";
string result = TestReflector.InvokeNonPublicMethod<string>(
"MyPrivateMethod", myClass, string1, string2 );
This code will support any non-public method with any number of parameters and any return type, except void. If you do need void support, its a simple adaptation of this code. Hope this helps!
Wednesday, April 25, 2007
Thanks to everyone who attended my mock objects talk at Innotech today, I hope it wasn't too obvious that it was the first time I've presented at a conference ;-) As promised, I've posted my slides and source code here. Sorry about the ads, but Blogger doesn't support file uploads and this site was the best I could find on short notice. If you're here for the links, here you go:
- Rhino Mocks: http://shrinkster.com/ocn
- WSCF: http://shrinkster.com/oco
- Wikipedia Article: http://shrinkster.com/ocp
- Pragmatic Unit Testing: http://shrinkster.com/ocq
- Martin Fowler’s Article: http://shrinkster.com/ocr
- XUnit Test Patterns: http://shrinkster.com/ocs
Posted at 1:50 PM