Reputation: 1438
I have a MyClass I want to test.
I have a TestMyClass class I'm going to use for this.
In MyClass I have several private variables.
I want to run tests using these private variables in TestMyClass.
I can just go and change all these private variables to public and then use them as objects in TestMyClass, but is there a way to do the testing without increasing the visibility of these variables? That is without manually going in to TestMyClass, deleting the private visibility marker and entering a "public" visibility market.
Thanks!
Upvotes: 1
Views: 1004
Reputation: 5758
its not adviced to test private memebers directly. The code should be designed in such a way that these private members will be indirectly called by public (interface) methods (example in your case: You can have setters and getters for member variables).
But you can use the Java Reflection API if you absolutely want to test private members.
Upvotes: 4
Reputation: 8846
As explained in other answers, it is not necessary/advised to test private methods and/or access private fields. If you really want/have to do this, then PowerMock is the way to go.
If you have to access private attributes to set them, then Spring's ReflectionUtils can be very helpful. If you are using mockito, you can also use the @InjectMocks annotation, which will inject any @Mock
-annotated attribute in your test class in the tested object.
Otherwise, there is still the possibility to change a public
access to a protected
or package private
access, which will be much more restrictive than public
.
Upvotes: 2
Reputation: 16090
What's wrong with interacting with your private variables using getters/setters? You can use a setUp()
/@Before
method in your test class to set up the state you wish to test. For example:
public class MyClass {
private int myInt;
public void setMyInt( int i ) { this.myInt = i; }
public int getMyInt() { return this.myInt; }
public void addsTo( int add ) { return myInt + add; }
...
}
public class TestMyClass {
MyClass my = new MyClass();
@Before public void setup() { my.setMyInt( 42 ); }
@Test public void testIs42() { assertEqual( "MyInt is 42" , my.getMyInt() , 42 ); }
@Test public void testAddsTo() { assertEqual( "addsTo() works" , my.addsTo( 10 ) , 52 ); }
}
Makes sense? In this manner you only interact with the private variables through public methods. The addsTo()
example is to illustrate that you would normally test the public methods the class exposes, not the getters/setters.
On a similar note, I often find myself changing method visibility from private to protected to allow testing class methods.
Cheers,
Upvotes: 1
Reputation: 16152
One solution is to mark them as protected, then have a MyClassTestSupport that exposes them using getters/setters. However, this pattern doesn't work very well if your class is a base class for others...
Upvotes: 1
Reputation: 22730
Why not provide setter / getter and use them instead of exposing variables?
Upvotes: 2