JUnit Testing private variables?

JavaUnit TestingVariablesJunitPrivate

Java Problem Overview


I have been assigned the task of unit testing a class that I never worked directly on with JUnit, and am strictly forbidden to change the code in the package. This is usually no issue, since most of our unit testing is just for functionality and input/output consistency, which can be done simply by running routines and checking their return values.

However, occasionally there is a need to check a private variable within the class, or directly edit a private variable to check some internal behavior. Is there a way to gain access to these, whether through JUnit or any other way, for the purpose of unit testing without actually changing any of the code in the original source package? And if not, how do programmers handle this issue in the real world where a unit tester may not be the same person as the coder?

Java Solutions


Solution 1 - Java

First of all, you are in a bad position now - having the task of writing tests for the code you did not originally create and without any changes - nightmare! Talk to your boss and explain, it is not possible to test the code without making it "testable". To make code testable you usually do some important changes;

Regarding private variables. You actually never should do that. Aiming to test private variables is the first sign that something wrong with the current design. Private variables are part of the implementation, tests should focus on behavior rather of implementation details.

Sometimes, private field are exposed to public access with some getter. I do that, but try to avoid as much as possible (mark in comments, like 'used for testing').

Since you have no possibility to change the code, I don't see possibility (I mean real possibility, not like Reflection hacks etc.) to check private variable.

Solution 2 - Java

Yeah you can use reflections to access private variables. Altough not a good idea.

Check this out:

http://en.wikibooks.org/wiki/Java_Programming/Reflection/Accessing_Private_Features_with_Reflection

Solution 3 - Java

Reflection e.g.:

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }
}
PrivateObject privateObject = new PrivateObject("The Private Value");

Field privateStringField = PrivateObject.class.
            getDeclaredField("privateString");

privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);

Solution 4 - Java

Despite the danger of stating the obvious: With a unit test you want to test the correct behaviour of the object - and this is defined in terms of its public interface. You are not interested in how the object accomplishes this task - this is an implementation detail and not visible to the outside. This is one of the things why OO was invented: That implementation details are hidden. So there is no point in testing private members. You said you need 100% coverage. If there is a piece of code that cannot be tested by using the public interface of the object, then this piece of code is actually never called and hence not testable. Remove it.

Solution 5 - Java

I can't tell if you've found some special case code which requires you to test against private fields. But in my experience you never have to test something private - always public. Maybe you could give an example of some code where you need to test private?

Solution 6 - Java

If you create your test classes in a seperate folder which you then add to your build path,

Then you could make the test class an inner class of the class under test by using package correctly to set the namespace. This gives it access to private fields and methods.

But dont forget to remove the folder from the build path for your release build.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondonnytonView Question on Stackoverflow
Solution 1 - JavaAlexander BeletskyView Answer on Stackoverflow
Solution 2 - JavaAlfredo OsorioView Answer on Stackoverflow
Solution 3 - JavabpgergoView Answer on Stackoverflow
Solution 4 - JavaMKKView Answer on Stackoverflow
Solution 5 - JavaThomasArdalView Answer on Stackoverflow
Solution 6 - JavaAndrew pView Answer on Stackoverflow