JUnit Testing private variables?

125,909

Solution 1

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 2

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 3

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

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.

Share:
125,909
donnyton
Author by

donnyton

Updated on July 05, 2022

Comments

  • donnyton
    donnyton almost 2 years

    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?

  • Kwebble
    Kwebble almost 13 years
    Having separate developers for code and tests could be an advantage since it requires 2 persons to interpret the specifications. If they differ in interpretation the requirements were not clear enough, the tests will probably fail and you've detected possible errors. Great!
  • Alexander Beletsky
    Alexander Beletsky almost 13 years
    @Kwebble my experience shows that separation "coders" & "testers" is a really bad practice. )
  • donnyton
    donnyton almost 13 years
    Indeed, there are some design issues in the class (which is actually an implementation of a singleton) that we will need to address eventually. It's for reasons beyond my (and my boss's) control that I am not allowed to touch the code itself. This specific issue appeared because while there were ways to change a particular private field, all those routines would have caused huge side effects that we wanted to avoid.
  • Kwebble
    Kwebble almost 13 years
    @alexanderb sure, it's possible that it doesn't fit in the development team or the process. And there are other ways of making sure the implementation fits the requirements, like code review or functional tests. But I think it might uncover errors earlier.
  • Kwebble
    Kwebble almost 13 years
    @donnyton: I hope you don't get a failed test, because that would require changes to the code anyway. With possible the same effects.
  • donnyton
    donnyton almost 13 years
    Unfortunately I cannot give example code. The testing of private members comes from a managerial requirement of having 100% code covering tests (as opposed to simply functional, or input/output tests). Not very useful if you ask me, but it is an unfortunate required protocol that is plaguing the programmers.
  • ThomasArdal
    ThomasArdal almost 13 years
    Sound like your manager attended some crappy course, telling him/her that 100 % code coverage is a great idea. That just makes me sad. I feel with you :)
  • simpatico
    simpatico almost 13 years
    and check out dp4j.com to avoid writing the reflection code yourself
  • IgorGanapolsky
    IgorGanapolsky over 11 years
    I get an error "no such field exception" when I try to use your technique.
  • tbroberg
    tbroberg over 10 years
    Often the code can't be unit tested from the public interface without modification.
  • Haris Osmanagić
    Haris Osmanagić over 10 years
    Assuming this is a real task (and not just a task with which a boss wants to see how you code ;)), this is another reason a boss/project manager has to be someone already involved in software development/testing.
  • Ewoks
    Ewoks over 6 years
    would be good if you elaborate why is not good idea but you still proposed it..
  • Gentle
    Gentle over 5 years
    After viewing tons of posts regarding this issue. finally got the solution that helped me out +1.
  • ACV
    ACV over 3 years
    You don't actually provide an answer to the question. And I don't see why you should not access private variables in your tests. How do you test immutable classes then?
  • John Glen
    John Glen over 3 years
    I made a class with a private constant that was used as a end of file hash for file saving. I have to pass the hash into the functions to make it testable though, because the program is supposed to load old files if it finds a bad hash, and the only way to test this is to feed it a new hash. Could probably call that bad design.
  • Adrian B.
    Adrian B. over 2 years
    the above approach works only if the field is declared in the target not, not in a parent class. There are other methods in the Class class that allow you to get your hands on parent declared fields instead of getDeclaredField(String).
  • Adrian B.
    Adrian B. over 2 years
    it's a good idea to add a summary of the solution in your answer besides the link, as the link may not be available in the future.