18

I use PowerMock 1.4.7 and JUnit 4.8.2

I need to mock only some static methods and I want others (from the same class) just to return original value. When I mock with mockStatic and don't call when().doReturn() all static methods return their defaults - like null when returning Object or false when returning boolean...etc. So I try to use thenCallRealMethod explicitly on each static method to return default implementation (means no mocking/ no fakes) but I don't know how to call it on every possible arguments variations (= I want for every possible input call original method). I only know how to mock concrete argument variation.

Eric
  • 6,563
  • 5
  • 42
  • 66
Michal Bernhard
  • 3,853
  • 4
  • 27
  • 38
  • 1
    Best answer and useful one https://www.codota.com/code/java/methods/org.powermock.api.mockito.PowerMockito/stub – DecKno Feb 14 '20 at 13:05

4 Answers4

32

You can use a spy on your static class and mock only specific methods:

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyStaticTest.MyStaticClass.class)
public class MyStaticTest {

public static class MyStaticClass {
    public static String getA(String a) {
        return a;
    }
    public static String getB(String b) {
        return b;
    }
}

@Test
public void should_partial_mock_static_class() throws Exception {
    //given
    PowerMockito.spy(MyStaticClass.class);
    given(MyStaticClass.getB(Mockito.anyString())).willReturn("B");
    //then
    assertEquals("A", MyStaticClass.getA("A"));
    assertEquals("B", MyStaticClass.getA("B"));
    assertEquals("C", MyStaticClass.getA("C"));
    assertEquals("B", MyStaticClass.getB("A"));
    assertEquals("B", MyStaticClass.getB("B"));
    assertEquals("B", MyStaticClass.getB("C"));
}

}
denis.solonenko
  • 11,645
  • 2
  • 28
  • 23
  • 5
    Although this works, be careful when using matcher arguments. If you were to use _Mockito.any()_ and you're trying to stub a spy's method, the actual getB() impl is invoked during the evaluation of the stubbing statement. If getB() fails to handle null arguments, a NPE will be thrown. – Luciano van der Veekens Feb 20 '17 at 16:12
  • 11
    what is "given"? – alexpfx Apr 17 '18 at 12:59
  • This did not work for me. I had to replace .spy(..) with PowerMockito.mockStatic(...) to get it working; which refutes the authors intended solution. – Stevers Oct 23 '18 at 18:11
  • This didn't work for me, even through multiple iterations, even with @LucianovanderVeekens comments. More explanation please? – gagarwa Jun 03 '20 at 13:41
17

You can also use the stubbing API:

stub(method(MyStaticClass.class, "getB")).toReturn("B");

Edit:

To use stub and method statically import methods from these packages:

  1. org.powermock.api.support.membermodification.MemberModifier
  2. org.powermock.api.support.membermodification.MemberMatcher

For more info refer to the documentation

R. Oosterholt
  • 7,720
  • 2
  • 53
  • 77
Johan
  • 37,479
  • 32
  • 149
  • 237
  • 2
    This approach worked for me, but the answer from denis.solonenko did not. It's hard to understand when to use doReturn, when, given, and stub, which all claim to do about the same thing. Each works sometimes and not others – Victor Grazi Jan 08 '15 at 14:45
  • This approach worked for me while doing partial mocking with Static class. – srinannapa May 12 '15 at 18:40
  • 1
    Thanks, please add `stub` method scope – Mrusful Apr 17 '16 at 15:22
  • How do you use this? Can you please provide the entire code example. – etech May 17 '16 at 22:27
  • I've added instructions on which packages to statically import methods from now – Johan May 18 '16 at 06:34
  • One problem with this approach is, I cant say for e.g: if my first argument is "abc": stub(method(MyStaticClass.class, "getB", "abc")).toReturn("B"); It does not work – Tarun Aug 08 '23 at 06:18
1

I managed to use spy and doReturn to achieve it.

class MyStatic {
    static String foo() { return "foo"; }
    static String foobar() { return foo() + "bar"; }
}

@Test
public void thisShouldSpyStaticMethods() {
    // arrange
    spy(MyStatic.class);
    doReturn("mocked foo").when(MyStatic.class);
    MyStatic.foo();

    // act
    final String result = MyStatic.foobar();

    // assert
    assertThat(result).isEqualTo("mocked foobar");
}

The doReturn followed by a call to the method to be mocked looks weird (at least to me), but seems to do the trick.

Using spy with when(MyStatic.foo()).thenReturn("mocked foo") doesn't work for me.

PowerMockito's documentation on mocking static method.

Community
  • 1
  • 1
Dapeng Li
  • 3,282
  • 1
  • 24
  • 18
0

Based on this question PowerMockito mock single static method and return object

PowerMockito.mockStatic(MyStaticClass.class);

alone does not mock all methods (in recent versions of PowerMockito at least), only enables mocking later of individual methods.

tkruse
  • 10,222
  • 7
  • 53
  • 80