5

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.

Ahmad
  • 12,886
  • 30
  • 93
  • 146
  • You are calling `methodUsingThePrivateMethod()` on the mock object, which in turn is calling `methodIWantToMock("some string")` internally. What behavior were you expecting here? – Tim Biegeleisen Jul 01 '16 at 23:53
  • That's correct, however through debugging I've found out that PowerMockito calls `methodIWantToMock()` when I run the `doReturn().when()` command. It doesn't wait for `methodUsingThePrivateMethod()` to call it. – Ahmad Jul 02 '16 at 00:14
  • I found this behavior through debugging. If I run the test (without debugging), the test crashes because of a `NullPointerException` generated because when the `doReturn(...).when(...)` command is executed, PowerMockito runs the private method while passing `null` as the input, and so when `String y = x.trim();` is executed inside `methodUsingThePrivateMethod()`, a `NullPointerException` is generated. Bottom line === the command `coiSpy.methodUsingThePrivateMethod();` is NEVER INVOKED. – Ahmad Jul 02 '16 at 00:19

1 Answers1

3

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 ...

  }
}
Ahmad
  • 12,886
  • 30
  • 93
  • 146
  • for this line: PowerMockito.doReturn(null).when(coiMock, "methodIWantToMock", any(String.class)); // coiMock is not able to call methodIWantToMock, right? – Mingzhong Apr 19 '19 at 21:48