My opinion has always been that private methods don't need testing as you should be testing what is available. A public method. If you can't break the public method does it really matter what the private methods are doing?
–
RigApr 12 '12 at 18:22

I disagree. Sometimes a private method is just an implementation detail, but it still is complex enough that it warrants testing, to make sure it works right. The public interface may be offering a too high level of abstraction to write a test which directly targets this particular algorithm. It's not always feasible to factor it out into a separate class, for due to the shared data. In this case I'd say it's OK to test a private method.
–
quant_devAug 14 '11 at 8:04

4

@Hippo: if your class has a private method that is never called, it is dead code and you do not need it. –
–
Steven A. LoweAug 14 '11 at 10:56

6

Of course delete it. The only possible reason not to delete a function you aren't using is if you think you may need it in the future, and even then you should delete it but note the function in your commit logs, or at least comment it out so that people know it's extra stuff they can ignore.
–
jhockingAug 14 '11 at 11:44

21

@quant_dev: Sometimes a class needs to be refactored into several other classes. Your shared data can be pulled into a separate class too. Say, a "context" class. Then your two new classes can refer to the context class for their shared data. This may seem unreasonable, but if your private methods are complex enough to need individual testing, it's a code smell that indicates your object graph needs to become a little more granular.
–
PhilJul 17 '12 at 14:47

In general, I would avoid it. If your private method is so complex that it needs a separate unit test, it often means that it deserved its own class. This may encourage you to write it in a way which is reusable. You should then test the new class and call the public interface of it in your old class.

On the other hand, sometimes factoring out the implementation details into separate classes leads to classes with complex interfaces, lots of data passing between the old and new class, or to a design which may look good from the OOP point of view, but does not match the intuitions coming from the problem domain (e.g. splitting a pricing model into two pieces just to avoid testing private methods is not very intuitive and may lead to problems later on when maintaining/extending the code). You don't want to have "twin classes" which are always changed together.

When faced with a choice between encapsulation and testability, I'd rather go for the second. It's more important to have the correct code (i.e. produce the correct output) than a nice OOP design which doesn't work correctly, because it wasn't tested adequately. In Java, you can simply give the method "default" access and put the unit test in the same package. Unit tests are simply part of the package you're developing, and it's OK to have a dependency between the tests and the code which is being tested. It means that when you change the implementation, you may need to change your tests, but that's OK -- each change of the implementation requires re-testing the code, and if the tests need to be modified to do that, then you just do it.

In general, a class may be offering more than one interface. There is an interface for the users, and an interface for the maintainers. The second one can expose more to ensure that the code is adequately tested. It doesn't have to be a unit test on a private method -- it could be, for example, logging. Logging also "breaks encapsulation", but we still do it, because it's so useful.

Testing of private methods would depend on their complexity; some one line private methods wouldn't really warrant the extra effort of testing (this can also be said of public methods), but some private methods can be just as complex as public methods, and difficult to test through the public interface.

My preferred technique is to make the private method package private, which will allow access to a unit test in the same package but it will still be encapsulated from all other code. This will give the advantage of testing the private method logic directly instead of having to rely on a public method test to cover all parts of (possibly) complex logic.

If this is paired with the @VisibleForTesting annotation in the Google Guava library, you are clearly marking this package private method as visible for testing only and as such, it shouldn't be called by any other classes.

Opponents of this technique argue that this will break encapsulation and open private methods to code in the same package. While I agree that this breaks encapsulation and does open private code to other classes, I argue that testing complex logic is more important than strict encapsulation and not using package private methods which are clearly marked as visible for testing only must be the responsibility of the developers using and changing the code base.

Private method before testing:

private int add(int a, int b){
return a + b;
}

Package private method ready for testing:

@VisibleForTesting
int add(int a, int b){
return a + b;
}

Note: Putting tests in the same package is not equivalent to putting them in the same physical folder. Separating your main code and test code into separate physical folder structures is good practice in general but this technique will work as long as the classes are defined as in the same package.

First of all, as other authors suggested: think twice if you do really need to test private method. And if so, ...

In .NET you can convert it into "Internal" method, and make package "InternalVisible" to your unit test project.

In Java you can write tests itself in the class to be tested and your test methods should be able to call private methods as well. I don't really have big Java experience, so that's probably not the best practice.

As an example, if you have a class named 'MyClass' with a private method named 'myPrivateMethod' which take a String as parameter an update its value to 'this is cool testing !', you can do the following junit test:

This library also enables you to replace any bean properties (no matter they are private and no setters are written) by a mock, and using this with Mockito or any other mock framework is really cool. The only thing you have to know at the moment (don't know if this will be better in next versions) is the name of the target field / method you want to manipulate, and its signature.

While reflection will enable you to test private methods, it is not good for detecting uses of them. If you change the name of a private method, this will break your test.
–
RichardNov 27 '12 at 10:42

1

The test will break yes, but this is a minor issue from my point of view.Of course i fully agree about your explanation below on the package visibility (with tests classes in seperate folders but with same packages), but sometimes you don't really have the choice. For example if you have a really short mission in an enterprise which doesn't apply "good" methods (test classes not in the same package, etc.), if you don't have time to refactor existing code on which you are working / testing, this is still an good alternative.
–
kijNov 27 '12 at 11:14

What I normally do in C# is make my methods protected and not private.
It's a slightly less private access modifier, but it hides the method from all classes that do not inherit from the class under test.

Any class that doesn't inherit directly from classUnderTest has no idea that methodToTest even exists. In my test code, I can create a special testing class that extends and provides access to this method...

protected is part of the public API and incurs the same limitations (can never be changed, must be documented,...). In C# you can use internal together with InternalsVisibleTo.
–
CodesInChaosDec 13 '13 at 11:03

Unit test case means testing the unit of code. It does not mean testing the interface because if you are testing the interface, that does not mean you are testing the unit of code. It becomes kind of a black box testing. Also, it is better to find issues on the smallest unit level than determining the issues on the interface level and then trying to debug that which piece was not working.
Therefore, unit test case should be tested irrespective of their scope. Following is a way to test private methods.

If you are using java, you can use jmockit which provides Deencapsulation.invoke to call any private method of the class under testing. It uses reflection to call it eventually but provides a nice wrapper around it. (https://code.google.com/p/jmockit/)

You can test private methods easily if you put your unit tests in an inner class on the class you are testing. Using TestNG your unit tests must be public static inner classes annotated with @Test, like this:

You are suggesting including test code (and additional inner classes) in the actual code of the package that is deployed?
–
MichaelTApr 11 '13 at 3:36

1

The test class is an inner class of the class you want to test. If you don't want those inner classes to be deployed you can just delete the *Test.class files from your package.
–
Roger KeaysApr 11 '13 at 7:49

1

I don't love this option, but for many it's probably a valid solution, not worth the downvotes.
–
Bill KMay 8 '13 at 17:15

@RogerKeays: Technically when you do a deployment, how do you remove such "test inner classes"? Please don't say you cut them by hand.
–
gyabrahamDec 13 '13 at 10:54

I don't remove them. Yes. I deploy code that is never executed at run time. It really is that bad.
–
Roger KeaysDec 15 '13 at 1:14