Recently I ran into a problem using .NET accessor methods to unit test private methods. I was able to resolve the problem, but in doing so ended up abandoning accessor methods in favor of a simpler approach (using reflection).
But should you even test private methods?It's a nuanced question. On one hand, it seems reasonable to break a class into small, purposeful private methods (exposing the main points of the class publicly) but still test the smallest possible chunks of functionality by testing those private methods in addition to the public ones. On the other, testing only public methods should exercise those private methods enough, and testing private methods can make your test code more brittle to change. There's a good table here with more arguing points.
For my purposes, I decided that I should.
What's a private accessor method?
But how do you get at privates? The default .NET unit test suite (MSTest) provides a seemingly handy facility within Visual Studio to easily do this by generating so called "private accessors".
Just right click on a private method in your code like so
then click "Create Private Accessor" and point it to a project containing your test code. and the tool magically provides proxy types (with the suffix "_Accessor") that expose these private methods publicly and that you can use from within your unit tests to access these private members like this:
var myObject = new MyClass_Accessor();
var result = myObject.PrivateMethod();
How useful, right?
I ran into trouble when I had a private method that returned a generic list of private classes. When I generated an accessor for the method, an accessor for the private class was also generated so that the accessor method actually returned a list of "MyPrivateClass_Accessor" types instead of "MyPrivateClass" types.
This generated code actually gives an error, and seems to be a bug in Visual Studio 2008. MyPrivateClass_Accessor derives from MyPrivateClass, and while you can cast a derived class to its base class, in .NET you can't cast a list of derived classes to a list of its base classes (as I assume it's doing internally in the generated code).
I suppose they're working to fix this.
A simpler alternative
var myObject = new MyClass();
var result = (List<MyPrivateClass>) myObject.CallMethod("PrivateMethod");
Sure, there's extra casting work and you have to use nasty string literals for the method names, but this is test code after all, and if it breaks you should know quickly from a regular test run.
A lessonOne of the hazards, it seems, working with Microsoft tools is the strong focus on tooling itself. This can sometimes get in the way of more elegant solutions based on simpler principles.
Not that all or most of the tools are bad (a lot of them I feel make me more productive), but it's a glamorous trap that you should be aware of.