How to write unit tests around private methods

11,496

Solution 1

Do you want to be able to call your private method in test and see how it works?

You can derive from your class and add public method that will call method you want to test. Very simple. Although I wouldn't advice testing private methods. I can't think of single reason to do it. I would love to see example that will change my mind.

Edit: Since this answer still gets some traffic I share this link. This blog post was created around 4 years after I posted my answer: https://enterprisecraftsmanship.com/posts/unit-testing-private-methods/

Solution 2

If you can't meaningfully test the private methods of a class via the public methods then that would suggest something is wrong with the design of the class. If it is hard to test the class so that you wish to break down the tests to test a subset of its functionality then I would suggest breaking the class into its logical pieces and testing those individually.

Perhaps you have an opportunity to refactor the code so that the private methods become the public methods of some other class(es). A good example is a class that schedules some work on a timer to be processed at a later time. The work method would likely be implemented as private method making it difficult to test in a simple way without scheduling a timer and waiting around for it to execute the work method. Not ideal in a test where execution times should be very quick. A simple way around this is to split the scheduling work code into two seperate classes. The private work method then becomes the public method of the Worker class making it very easy to test. Whilst splitting the scheduling and worker code means you will struggle to achieve 100% coverage, you will at least cover the work code. A way around the problem is to use something like Quartz.net for implementing the scheduler class so that you can unit test the scheduler quite easily and the worker code as well.

Solution 3

I have read this question (How do you unit test private methods?) but would like to know if the accepted answer is still the best answer or after years there is a better way.

I would avoid the accepted answer.

I can jump into a tirade about testing the public interface and not worrying about the internals, but that might not be realistic.

There are two immediate options I can see:

  • Reflection to see the method, sort of a hack, but at least you can get some sort of test going. This is also likely the easiest to get working quickly.
  • Abstract the private method behaviour using something like the Strategy pattern and inject the behaviour into the object itself (or have the object internally new up the relevant strategy manually). This separate strategy item can then be tested independently.

That said, you shouldn't find yourself in this situation very often. If you do, you need to take a step back and review how you are designing your classes and possibly review them with a view to making them more open and testable.

Solution 4

In VS 2005, 2008 and 2010, you may have private accessor. You right click on a private function, and select "Create private accessor" ...

In VS 2012, this feature had somehow gone. The only handy way is to use PrivateObject. You may check MSDN for examples of using PrivateObject.

Share:
11,496
Mr. Mr.
Author by

Mr. Mr.

Updated on June 17, 2022

Comments

  • Mr. Mr.
    Mr. Mr. almost 2 years

    I am trying to unit test a class that has public and private methods and I want to unit test a particular method that has been set as private (protected abstract on the base). I cannot make the method public and I do not want to go through the full process to get this method tested, I am only concerned that the input argument to this method and the return meet an expectation.

    I do not want to make the method public as this question highlights:

    Making a private method public to unit test it...good idea?

    My question would be, what are the various ways of testing private methods and which technique should I favour and why?

    I have read this question (How do you unit test private methods?) but would like to know if the accepted answer is still the best answer or after years there is a better way.

    If this question is considered a duplicate of How do you unit test private methods? I will add my comment there and ask for an update, please advise.