Ahmad Ahmad - 4 months ago 25
Java Question

PowerMockito is calling the method when I use doReturn(..).when(....)

I'm new to PowerMockito and there's a behavior it's displaying which I don't understand. The following code explains my issue:

public class ClassOfInterest {

private Object methodIWantToMock(String x) {

String y = x.trim();

//Do some other stuff;
}

public void methodUsingThePrivateMethod() {

Object a = new Object();
Object b = methodIWantToMock("some string");

//Do some other stuff ...
}
}


I have a class which contains a private method that I want to mock called
methodIWantToMock(String x)
. In my test code, I'm doing the following:

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassOfInterest.class)
public class ClassOfInterestTest {

@Test
public void someTestMethod() {

ClassOfInterest coiSpy = PowerMockito.spy(new ClassOfInterest());

PowerMockito.doReturn(null).when(coiSpy, "methodIWantToMock", any(String.class));

coiSpy.methodUsingThePrivateMethod();

//Do some stuff ...

}
}


According to the above code, PowerMockito should simply return a null whenever
methodIWantToMock
is called inside
methodUsingThePrivateMethod()
when I run the test above. However what actually happens is that when this command is run:
PowerMockito.doReturn(...).when(...)
, PowerMockito is actually calling
methodIWantToMock
right then and there !!
Why is it doing that ?? At this stage I only wanted to specify how it should mock the private method once it's eventually called when the
coiSpy.methodUsingThePrivateMethod();
line is run.

Answer

So I figured out a solution that works for me. Instead of using a spy, I used a mock and then told PowerMockito to call the real method when methodUsingThePrivateMethod() is called inside my mocked object. It's essentially doing the same thing as before but just using a mock instead of a spy. This way, PowerMockito does NOT end up calling the private method whose behavior I'm trying to control using PowerMockito.doReturn(...).when(...). Here is my modified test code. The lines I changed/added are marked:

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassOfInterest.class)
public class ClassOfInterestTest {

  @Test
  public void someTestMethod() {

  //Line changed:
  ClassOfInterest coiMock = PowerMockito.mock(new ClassOfInterest());

  //Line changed:
  PowerMockito.doReturn(null).when(coiMock, "methodIWantToMock", any(String.class));

  //Line added:
  PowerMockito.when(coiMock.methodUsingThePrivateMethod()).thenCallRealMethod();

  coiSpy.methodUsingThePrivateMethod();

  //Do some stuff ...

  }
}