How to test private methods

A very common question I hear from developers is “How do I write tests for private methods?”. My immediate answer is “You don’t!”. Technically, if you’re in C# Land, you can instantiate the class and then use Reflection to call the private method. But please don’t!

Say you have some class like this one:

Of course, instead of comments, you’d have the actual code. You get the point.

You then decide to clean things up a bit and extract the “make sure all the ingredients are in” code into a separate, private ValidateIngredients method, like so:

That’s usually the moment when developers ask “how do I test that private method?”. If we have tests for the main method (DoTheMagic, in this example), then ValidateIngredients already get test coverage.

Quite often, when developers feel strong about having separate tests for a private method, there’s a clear indication that the private method should really be a public method on a separate class. Think Single Responsibility Principle.

Following the example above, we create a Validator class and move our validation logic in there:

And then we use that validator in the previously shown class:

You’ve probably noticed that we also introduced an IValidatePotion interface. Think Dependency Inversion Principle. One of the benefits here is being able to isolate tests for the AwesomenessPotion and AswesomenessPotionValidator classes.

  1. #1 by Thomas on May 18, 2020 - 9:58 am

    “Quite often, when developers feel strong about having separate tests for a private method, there’s a clear indication that the private method should really be a public method on a separate class.”

    Yes, 100%. Also, developers inexperienced with unit testing sometimes think there need to be tests for every single method. (Side note, this and code coverage requirements is how we get unit tests for getters/setters.)

    • #2 by claudiolassala on May 18, 2020 - 2:51 pm

      Yup, I have a separate blog post lined up to talk about code coverage. 🙂 Thanks for reading and taking the time to leave a comment, Thomas.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: