How to unit test private methods in BDD / TDD?

When you write code test-first, you write against the public interface. There are no private methods at this point.

Then you write the code to pass the test. If any of that code gets factored into a private method, that's not important -- it should still be there only because it is used by the public interface.

If the code isn't written test first, then -- in .net, anyway -- reflection can be used to directly prod private methods; though this is a technique of last resort.


Private methods are internal implementation details. They should not be tested directly, as they will be tested indirectly via testing your public interface. If for some reason a private method is not covered when your public interface is fully tested, then the private method is not required, and it should be removed.

Generally, it is a bad idea to bind test code to private implementation details. That couples your test to those private details, reducing your freedom to change those details at will, even if they don't affect the publicly facing interface and behavior. That increases the amount of effort required to write and maintain your unit tests, which is a negative thing. You should strive for as much coverage as possible, while only binding to the public interface.


Short answer: You don't test private methods.

If you have programmed well, the code coverage of your tests should be testing private methods implicitly.


If a private method method exists, it's there to be used by a public method. Therefore I'd write a test for the public method.

I write my tests to test the public parts of a class. If the class is well designed then the private parts get tested by default.

If the private method isn't called from a public method, then why does it exist?

In your case I'd do the following

* Write failing test for the public method
* Write public method that calls the private method that doesn't exist yet(test still fails as your class is incomplete
* Write the private method
* Test should now pass