Ankit
Ankit

Reputation: 135

How to test void method with private method calls using Mockito

I have the following piece of code

public class A extends B {
private boolean workDone = false;
@Override
public void publicMethod(boolean flag) {
  if (!workDone) {
    privateMethod();
    workDone = true;
  }
  super.publicMethod(flag);
 }
 private void privateMethod() {
  // some logic here
 }
}

I'm new to mocking. I have following doubts. I'm trying to test the public method.

  1. is it possible for me to assert the value of private variable workDone?
  2. is it possible to verify the method call in the super class?
  3. How can I mock the private method call in the method?

Upvotes: 3

Views: 8989

Answers (3)

kism3t
kism3t

Reputation: 1361

If you really want to verify it, you need to change your A class and extract the super call into a private method:

public class A extends B {

    private boolean workDone = false;

    @Override
    public void publicMethod(final boolean flag) {
        if (!workDone) {
            privateMethod();
            workDone = true;
        }
        callParentPublicMethod(flag);
    }

    private void callParentPublicMethod(final boolean flag) {
        super.publicMethod(flag);
    }

    private void privateMethod() {
        System.out.println("A: privateMethodCalled");
    }
}

after this is done you can use PowerMock to verify private method invocations:

  import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class })
public class ATest {

    @Test
    public void publicMethod_test_false() throws Exception {

        A spy = PowerMockito.spy(new A());
        spy.publicMethod(false);
        PowerMockito.verifyPrivate(spy).invoke("privateMethod");
        PowerMockito.verifyPrivate(spy).invoke("callParentPublicMethod", false);
    }

    @Test
    public void publicMethod_test_true() throws Exception {

        A spy = PowerMockito.spy(new A());
        spy.publicMethod(true);
        PowerMockito.verifyPrivate(spy).invoke("privateMethod");
        PowerMockito.verifyPrivate(spy).invoke("callParentPublicMethod", true);
    }
}

Hope this helps.

Upvotes: 3

acchu
acchu

Reputation: 21

  1. No. Private variables cannot be accessed other than via reflection. Which is usually not preferred, especially in unit tests.
  2. Yes, assuming you get some assertable change do to super class method call. Like the change in the boolean flag
  3. Yes you can using powermockito. For more see here. Testing Private method using mockito

Upvotes: 0

Timothy Truckle
Timothy Truckle

Reputation: 15622

When doing unittesting we verify the public observable behavior of the code under test. This is the return values delivered by the CUT and its communication with dependencies.

The private variable and the private methods inside the CUT are implementation details we don't want to test (explicitly) because we want them to be changeable without braking our test.

In rare cases the call to super class methods can be considered as "communication with dependency". In that case you create a spy() of the CUT. But usually this should be considered implementation detail too...

Upvotes: 0

Related Questions