Saturday, February 26, 2005

Unit testing private methods using reflection

Don't know how many other people have come across this problem, but a couple of days ago I was writing a class in C# and I decided I wanted a private method to perform some functionality. I knew the private method would contain some non-trivial logic, but didn't want to expose it to other classes that other developers were working on. I decided that the logic within the method was serious enough to warrant some unit tests, but how could I unit test considering the method was private. Normally I would make the argument that as long as I tested the public interface correctly, then I should be fine, however, I had a suspicion that this time was different, so I sought the advice of my fellow Readify colleagues, and the ever brilliant Mitch Denny came to the rescue with some sample code that used .net reflection to call into the private method.


TestVictim victim = new TestVictim();
Type victimType = typeof(TestVictim);
MethodInfo method =
victimType.GetMethod("PrivateMethodName",
BindingFlags.NonPublic BindingFlags.Instance);

//pass parameters in an object array
method.Invoke(victim, . . . .);


or in my case more along the lines of


Type victimType = typeof(VictimClass);
MethodInfo =
victimType.GetMethod("PrivateMethodName",
BindingFlags.NonPublic BindingFlags.Static);

//pass parameters in an object array
method.Invoke(null, . . . .);

as this was a static private method.

This worked a treat and I very quickly discovered the reason that I'd suspected I should go the extra mile and create this unit test. The very first time I ran my unit tests with just the most basic tests in place, I discovered one of those "doh" type bugs. Had I been attempting to just test the public interface, because there was considerable complexity in the public method that was using this private method I would have been looking in the wrong place for ages trying to debug the public interface, stepping into each line etc..., but because I'd spent 15 minutes setting up the unit test, when I did finally write the unit test for the public method, it worked first time.

Question: So when should you go to the extra effort of using reflection to unit test a private method?
Answer: When the private method contains non-trivial logic, and writing tests for the public interface won't make it obvious what's really happening or you won't be able to get decent code coverage from the public interface tests. There may be other times as well, but this is the rule I'm going to stick to for now.

1 comment:

  1. Hi Scott,

    There are also some frameworks out there that allow you to do it even more simply e.g.:

    Invoker.InvokeStatic("PrivateMethod", new object[0]);

    ReplyDelete