JUnit Testing private variables?
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.
donnyton
Updated on July 05, 2022Comments
-
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 almost 13 yearsHaving 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 almost 13 years@Kwebble my experience shows that separation "coders" & "testers" is a really bad practice. )
-
donnyton almost 13 yearsIndeed, 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 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 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 almost 13 yearsUnfortunately 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 almost 13 yearsSound 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 almost 13 yearsand check out dp4j.com to avoid writing the reflection code yourself
-
IgorGanapolsky over 11 yearsI get an error "no such field exception" when I try to use your technique.
-
tbroberg over 10 yearsOften the code can't be unit tested from the public interface without modification.
-
Haris Osmanagić over 10 yearsAssuming 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 over 6 yearswould be good if you elaborate why is not good idea but you still proposed it..
-
Gentle over 5 yearsAfter viewing tons of posts regarding this issue. finally got the solution that helped me out +1.
-
ACV over 3 yearsYou 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 over 3 yearsI 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. over 2 yearsthe 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. over 2 yearsit'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.