This post as you read from the title is about unit testing for private methods. Do we really need to test the private methods in the unit tests?
Unit testing private methods
Private methods are used to have the abstraction in classes and some times created for code resuability purposes.
If you are writing MS Tests for unit testing, then Microsoft provides a Private Object class through which you can test the private methods. But, I don't think this is a good idea.
If you want to test the private methods and achieve code coverage for the lines of code in the private methods the only way I see is to write more tests for the public API which utilizes the private method.
But, the output of the public API method can be different from the output of the private methods, in that case, we will have to assert only the value returned from the public API method.
Too much logic in the private methods
What if we had too much logic in the private method? Well, you could write many tests for your public API. This is not a bad idea. But, don't you see a hidden class in the private method (refactor the private method logic to have a separate class).
Extract that private method logic to a class and test the class instead of writing too many tests for the public API method.
The code base is too old and NO TESTS yet
Okay, this might be a special case. Think that the code base is old and is not having any unit tests until now. But the management now wants to have unit tests for the bug fix. The code is also not clean. The methods have too many lines of code and have some business logic to modify the fields and save it to the database.
As you figured out the fix and it is in the middle of that very long method. Also, we need to write unit tests for the fix, so we create a new private method for our fix and that should be tested or you could include your code code to make it even harder to read.
If we begin writing tests for the method, it would certainly take a very long time to write tests and pass them.
We can deal with the above problem in two ways
- Stub the portions of the code into a public method so that you can mock them in your tests and you can validate your fix alone in the unit tests.
- Writing tests for the entire method.
The first approach is damn easy! All you have to do is create some methods and make them public. But isn't this bad way of doing things? You are exposing the inner workings of your algorithm/program through an interface just for the purpose of writing unit tests.
Now, for the second approach of writing tests for the complete method, it involves you to understand the method and then write tests or mock the objects accordingly.
Instead of writing tests for the existing method, I think it is better to have a separate class (if you see the class hidden in a method) because you know the functionality/business logic of the code. So, if you can write everything in a separate method then you can just write tests for your class instead of testing the public API.
Writing unit tests is a good thing but if we have a private method I think making it public is a bad idea as it breaks the abstraction that we wanted in our code.
Private methods are not that bad, it signals that you are missing an abstraction.
- Don't aim to unit test the private methods just test the public API.
- If you think there's more logic in the private methods that need to be tested, write it in a separate class file.