papercuts
papercuts

Reputation: 1438

Is there a way to do unit tests using private variables without increasing their visibility?

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

Answers (6)

codeMan
codeMan

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

Bastien Jansen
Bastien Jansen

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

Anders R. Bystrup
Anders R. Bystrup

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

Tassos Bassoukos
Tassos Bassoukos

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

NPKR
NPKR

Reputation: 5506

use public setter and getters for that private Properties in a class

Upvotes: 2

Ajinkya
Ajinkya

Reputation: 22730

Why not provide setter / getter and use them instead of exposing variables?

Upvotes: 2

Related Questions