1

I've been reading a lot about unit testing recently and there seems to be a debate online about whether private methods should be tested or not.

If I have an interface that exposes one method, but that method is quite complex and calls multiple other private methods and also makes use of other objects, how do I go about testing that method? Surely I should be testing the smallest units possible, even though many of these will be private methods belonging to the class under test?

Is testing a method that is made up of multiple smaller methods really an integration test?

4

No, it's not an integration test. A unit test tests one unit of executable code, and in procedural languages that usually equates to a method.

The test must make sure that this unit of code does its own task correctly, and nothing else. If our method calls multiple private methods, then you must test the effect of all those private bits of code. For instance, if it constructs a complex object with many different attributes, then you must test the value of all those attributes. If it does different things in different circumstances, then you must exercise all those different circumstances - probably in multiple tests. There is no reason for writing only one test for one method; if the circumstances are different enough, then it's almost always clearer to write multiple tests with different fixtures than to cram it all into one test.

Of course, if your method really is too complicated, there may be a very good case for refactoring it into multiple smaller methods. But that is true completely independent of testing; the fact that one method should do exactly one thing is a good principle to follow to begin with. The main reason for refactoring is that it makes the business code easier to understand and extend. The fact that it makes testing easier is just a collateral benefit.

  • If all that foo does is call bar1, bar2 and bar3 then how do you test foo? Or is testing bar1, 2 and 3 enough? With other objects I know how to mock them but what's to be done within the class itself? – Eliezer Steinbock Oct 19 '14 at 16:11
  • 3
    foo presumably calls bar1 in order to help it get its own job done. The test must check that foo does its job, not how it does it. A unit test doesn't care whether the tested method uses subroutines, an unholy mess of inline cases or pure magic to do its job, it only cares that the job gets done. (This is one reason why having good test coverage doesn't guarantee code quality - you also need additional principles such as "do the simplest thing that could possibly work".) – Kilian Foth Oct 19 '14 at 16:17
1

First off, there seem to be many approaches to testing code automatically. The term "unit testing" seems to have been bastardized to mean any automated testing. In its pure form, a unit test tests only one method. A test for a method that calls other methods or library functions is often called a functional test. Integration testing usually spans multiple components, process or thread boundaries.

The questions you have to ask yourself are:

  1. Could any of the private methods fail to work?
  2. Might any of the private methods be useful for other methods in the class?
  3. If the master method is treated as a black box, are there parts of the code that won't be tested?

If you decide you want to test the private methods, there are several approaches:

  • Change the scope to public (I shudder when this is suggested, but I do it for completeness sake).
  • Change the scope to protected and create a subclass that accesses the formerly private methods for testing purposes.
  • Use introspection to access the private methods for testing purposes (again, I shudder, but it may be required).
  • Changing the scope just for testing is vile, public or not. – Telastyn Oct 19 '14 at 16:39
  • 1
    No, unit tests in their pure form are supposed to determine whether a given unit viewed in isolation conforms to its specification. As private helpers can never be part of an API specification, there is no use in unit testing them, or mocking private helpers in a different unit's test. However, I take the position that it can still be useful to test private helpers to determine whether they conform to this unit's programmer's expectations, and because fine-grained tests make it easier to localize errors. – amon Oct 19 '14 at 20:36
0

there seems to be a debate online about whether private methods should be tested or not.

Really? Where is this supposed debate?

If it's part of your software, it needs to work. Usually, that means testing it to make sure it works.

If I have an interface that exposes one method, but that method is quite complex and calls multiple other private methods and also makes use of other objects, how do I go about testing that method?

Step 1 - make it less complex. Seriously. If you find it hard to pull out the different bits to test them in isolation, it's going to be double touch to modify or reuse those different bits in a non-test scenario. Do yourself a favor and clean up the function.

Yes, yes, "but I've done all I can! This is an exceptional circumstance!", I've heard it before... Odds are, it's not really exceptional. So question 2:

Surely I should be testing the smallest units possible, even though many of these will be private methods belonging to the class under test?

Absolutely. But you also need to test the responsibility of the thing that aggregates those private methods together, to make sure it did that aggregation properly to get you your correct result. In an ideal world, that would mean treating it like a black box. Take some inputs, check that the outputs are as expected. In the real world, you'll likely have a lot of inputs/setup - but that's what you get for not simplifying the method in the first place.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.