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.
posted on Wednesday, December 31, 2003 3:36 PM
Feedback
#
re: unit testing private methods
StevePosted @ 12/31/2003 4:22 PMI've taken the approach you mentioned. I test the public interface to ensure the components do what I expect. Usually if something's wrong in one of the private methods the test for the public method "catches" the error.
#
re: unit testing private methods
Omer van KloetenPosted @ 1/1/2004 7:41 AMhttp://weblogs.asp.net/okloeten/archive/2003/11/01/35176.aspx#FeedBack
#
re: unit testing private methods
Alexander SafronovPosted @ 1/28/2004 11:31 AMThe major advantage of testing private details, is that it will immediately pint to the place that is broken. If something is broken inside private portions of the code, then even if testing of public interface found that something is wrong, you migth spend hours trying to find where specifically you made (for example) "off-by-one" error