unit testing private methods
Projects that use nUnit extensively often debate whether or not to test private methods. As one of our developers wrote, "In old C++ world we used to use 'friend' keyword to allow class FooTest to access ALL methods and fields of class Foo. This allowed us to perform 'white box' testing by verifying internal class state. This level of testing is preferable comparing to 'black box' testing, which tests only method outcome."
A similiar result could be achieved in C# by having the unit tests build into the same assembly as the classes they are testing and then to declare methods as 'protected internal' instead of protected and 'internal' instead of private. By using a multi-file assembly (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconbuildingmulti-fileassembly.asp) the tests can be in a seperate dll, and still access the internal methods of the business objects.
However, Visual Studio does not offer good support for multifile assemblies. Multifile assemblies must be linked with the command-line Assembly Linker, which makes build scripts and processes more complex.
I suggest that tests should be written only for the public methods. This offers several advantages:
- Users will use the public methods, so all functionality should be exposed there. - If there is code that doesn't affect a public method, you should take it out.
- Writing the tests against the interface improves the interface. - Users of the class have to program against the interface, if it isn't clear and easy to use, improve the interface. If you write tests against private methods, you may never notice that you don't have a public interface to perform some action.
- Tests are not tied to the internals of a class - If tests only test the public functionality, they won't have to be rewritten during performance tuning or other optimizations.
- If the tests are written against an interface, other classes that implement the same interface can be tested without changing the tests.