I have a Java unit testing question. First, let me describe a scenario. Let’s say I have a class called
IncomeTaxReturn that includes a method,
calculateRefund(). That method is public (meaning anybody can call it). I also have a bunch of other methods that are only used by
calculateRefund() that package up bits of logic so that the code is easier to understand and to test. The class might include methods like
The methods I’ve written to encapsulate bits of business logic produce a predictable output given a specific input, and I want to write tests for them. I may also have some tests for
calculateRefund(), but having tests for the other methods is a good practice because it helps to isolate problems when performing regression tests later.
Most Java projects keep tests in a directory structure parallel to the source for the application itself, making it easy to leave out the unit tests when building the application for distribution or deployment to the server.
I feel like the best practice is to mirror the package names between your application source and your tests. So if my
IncomeTaxReturn class is in
gov.irs.incometax then I put
TestIncomeTaxReturn in the same package,
gov.irs.incometax, only in the test directory. Then I just make sure that all of the classes for the application and tests are in the classpath when I want to run my tests.
So here’s the question. If I were not going to write any tests for the methods I was talking about, I’d make those methods private. If I want to test them, how do I handle the scope?
I can’t leave them as private because then my test cases can’t run them. So now I have to alter my code not to improve the application, but to make testing easier.
Obviously I could make the methods public, but that strikes me as a bad idea. Suddenly a bunch of internal methods that are really implementation details are part of the public interface of my class. From a purity standpoint, that’s a bad idea because someone else may come along and wonder what kind of API you’re providing. From a laziness standpoint, this approach stinks because when I reference the class in my IDE, I have to sift through all of those methods when I’m auto-completing a method name.
Protected scope is out, because unit tests usually subclass a generic test case, not the classes they’re testing.
I could leave out the scope entirely, leaving the methods with the default (package) scope. As long as I follow the practice of putting my tests in the same packages as the classes they test, this approach works, and is probably the right answer.
Is there another approach that’s recommended? Or do people generally just test against the public interfaces of their Java classes rather than testing the private methods that test bits of the business logic?