Should Private/Protected methods be under unit test?

You wrote:

In TDD development, the first thing you typically do is to create your interface and then begin writing your unit tests against that interface. As you progress through the TDD process you would end-up creating a class that implements the interface and then at some point your unit test would pass.

Please let me rephrase this in BDD language:

When describing why a class is valuable and how it behaves, the first thing you typically do is to create an example of how to use the class, often via its interface*. As you add desired behavior you end up creating a class which provides that value, and then at some point your example works.

*May be an actual Interface or simply the accessible API of the class, eg: Ruby doesn't have interfaces.

This is why you don't test private methods - because a test is an example of how to use the class, and you can't actually use them. Something you can do if you want to is delegate the responsibilities in the private methods to a collaborating class, then mock / stub that helper.

With protected methods, you're saying that a class which extends your class should have some particular behavior and provide some value. You could then use extensions of your class to demonstrate that behavior. For instance, if you were writing an ordered collection class, you might want to demonstrate that two extensions with the same contents demonstrated equality.

Hope this helps!


No, I don't think of testing private or protected methods. The private and protected methods of a class aren't part of the public interface, so they don't expose public behavior. Generally these methods are created by refactorings you apply after you've made your test turn green.

So these private methods are tested implicitly by the tests that assert the behavior of your public interface.

On a more philosophical note, remember that you're testing behavior, not methods. So if you think of the set of things that the class under test can do, as long as you can test and assert that the class behaves as expected, whether there are private (and protected) methods that are used internally by the class to implement that behavior is irrelevant. Those methods are implementation details of the public behavior.


I disagree with most of the posters.

The most important rule is: WORKING CODE TRUMPS THEORETICAL RULES about public/protected/private.

Your code should be thoroughly tested. If you can get there by writing tests for the public methods, that sufficiently exercise the protected/private methods, that's great.

If you can't, then either refactor so that you can, or bend the protected/private rules.

There's a great story about a psychologist who gave children a test. He gave each child two wooden boards with a rope attached to each end, and asked them to cross a room w/o touching their feet to the floor, as fast as possible. All the kids used the boards like little skis, one foot on each board, holding them by the ropes, and sliding across the floor. Then he gave them the same task, but using only ONE board. They pivoted/"walked" across the floor, one foot on each end of the single board -- and they were FASTER!

Just because Java (or whatever language) has a feature (private/protected/public) does not necessarily mean you are writing better code because you use it!

Now, there will always be ways to optimize/minimize this conflict. In most languages, you can make a method protected (instead of public), and put the test class in the same package (or whatever), and the method will be available for test. There are annotations that can help, as described by other posters. You can use reflection to get at the private methods (yuck).

The context also matters. If you're writing an API for use by external people, public/private is more important. If it's an internal project -- who really cares?

But at the end of the day, think about how many bugs have been caused by lack of testing. Then compare to how many bugs have been caused by "overly visible" methods. That answer should drive your decision.