Unit Testing Private Methods

It is somewhat frustrating that xUnit does not support the testing of private methods. Purists may say that is rightly so as unit tests should only target public methods. Unit testing private methods is considered anti-pattern. So if it works on the outside (public methods) do we really need to unit test the inside (private methods) ?

Unit testing is not about creating a series of tests for all methods. Doing so can be overkill. If your unit tests on public methods (your class’ contract with the outside world) continue to pass without issue do you really have any need to unit test private methods?

However from a pragmatic point of view, there are rare times, when working on a private method, having a series of unit tests can help. For example, a private method may be called multiple times from other private or public methods; it may be complicated; it may be badly written or difficult to understand or both; there may be no existing units tests for the class’s pubic methods; it may have some functionality that is not currently being consumed directly or indirectly by any public methods – this could be due to other work in progress or on hold but it is valid work towards a future feature.

At times a number of the above factors are at play. Before working on a private method by creating some unit tests that targets that method it gives me some assurance that ongoing work may not have broken some basic or essential behaviour of that method.

Person in front on computer with hands on their head in frustration
The frustration from code that badly needs attention but you want to avoid heavy refactoring

Should I Refactor?

If you perform a quick web search on unit testing of private methods, a general suggestion, is that the code should be refactored. Some comments are brief or absent with regards to the cost and effort. It is easy to say but not necessary easy to do.

A few voice that in some way you code/structure must “suck” because you are enquiring about unit testing of private methods. Even if the code you are working on is a mess – its a mess you may not be able to address.

In many scenarios refactoring the code is not likely to be an immediately available realistic option. Not all coding is performed under perfect conditions (are there any?) Real and pressing business needs often come into play.

One option, often suggested, is to move your private method into an internal class and make that method public. This can be a acceptable solution depending on your need. When a method is private you are declaring that it should only be consumed within its own container. By creating an internal class you are now allowing other classes (within the same assembly) access to it. Making this type of change to enable unit testing changes the method’s visibility and open for unintended/unplanned consumption.

Refactoring code could be further complicated, for example, if your private methods receives or returns other private types which may also be used by other methods,

Other Workarounds?

Some advise to temporarily change your method from private to public. This, in my view, is not a desirable solution and very risky for the obvious reason of failing to remember to change it back.

Other advice given is the creation of new public method(s) just for the purpose of being able to call your private methods. Again I think this is an undesirable solution.

Both these options change the class’s public interface (API). You may be committing (deliberately or accidentally) to long term maintenance of new API elements when there is no need for them other than for development and testing .

Summary

Unit testing of private methods is not normally desirable and when it is desired, it is, or the code you are working with can often be viewed as “anti-pattern”. Living in the real world working on new, fast changing and legacy code, having the tools to unit test private methods would be a pragmatic solution although not a pure or a best-practise one.

My workaround in C#/.NET to this dilemma, whilst quick and dirty, is to use reflection to call the private method within a test. I also try to ensure that the code is commented as such for whoever is the poor developer who works on the code after me 🙄.

Postscript...

Computer screen photo by Tima Miroshnichenko from Pexels

"Frustration" by Photo by Andrea Piacquadio from Pexels

 

Leave a Reply

Your email address will not be published. Required fields are marked *