How do I unit test (using xUnit) a class that has internal private methods, fields or nested classes? Or a function that is made private by having internal linkage (static
in C/C++) or is in a private (anonymous) namespace?
It seems bad to change the access modifier for a method or function just to be able to run a test.
The private methods are called by a public method, so the inputs to your public methods should also test private methods that are called by those public methods. When a public method fails, then that could be a failure in the private method.
When I have private methods in a class that are sufficiently complicated that I feel the need to test the private methods directly, that is a code smell: my class is too complicated.
My usual approach to addressing such issues is to tease out a new class that contains the interesting bits. Often, this method and the fields it interacts with, and maybe another method or two can be extracted in to a new class.
The new class exposes these methods as 'public', so they're accessible for unit testing. The new and old classes are now both simpler than the original class, which is great for me (I need to keep things simple, or I get lost!).
Note that I'm not suggesting that people create classes without using their brain! The point here is to use the forces of unit testing to help you find good new classes.
Just two examples of where I would want to test a private method:
SecurityManager
is not configured to prevent this).I understand the idea of only testing the "contract". But I don't see one can advocate actually not testing code - your mileage may vary.
So my tradeoff involves complicating the JUnits with reflection, rather than compromising my security & SDK.
Please see below for an example;
The following import statement should be added:
Now you can directly pass the object which has the private method, method name to be called, and additional parameters as below.
I recently had this problem and wrote a little tool, called Picklock, that avoids the problems of explicitly using the Java reflection API, two examples:
Calling methods, e.g.
private void method(String s)
- by Java reflectionCalling methods, e.g.
private void method(String s)
- by PicklockSetting fields, e.g.
private BigInteger amount;
- by Java reflectionSetting fields, e.g.
private BigInteger amount;
- by PicklockTesting private methods breaks the encapsulation of your class because every time you change the internal implementation you break client code (in this case, the tests).
So don't test private methods.