简体   繁体   中英

How can I mock a private static method with PowerMockito?

This is the same question as found here. Unfortunately, the accepted answer isn't working for me. I have a static utility class with private methods that I need to test. I find that when I mock methods like this:

PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);

I'm getting a null pointer exception because the getSomethingMethod() is actually being called. When I debug, I see that it isn't being called when I run the method I'm trying to test, but it is running when I am setting up the mock. Based on this site, it looks like that is what is supposed to happen when you create the mock in this format.

So then I try to set up the mock this way:

PowerMockito.spy(StaticUtil.class);        
PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod( someObjectArray, someStringArray, aBoolean, someList);

However, I am get an error from Eclipse that says I need to change the visibility of getSomethingMethod() to public. Isn't one of the big benefits of using PowerMockito that you can mock private methods? I need to mock this private static method (without actually calling the method during setup).

You have to use the exact syntax that they specify in the answer you linked . That syntax is doReturn(returnValue).when(Class, String, arguments); . Neither of the examples you've provided here use that example.


Here's some extended explanation. I've thrown together a sample test framework to demonstrate this:

Trying to run tests on this class:

package org.test.stackoverflow;

import java.util.Collections;
import java.util.List;

public class StaticUtil {
  public static void Wrapper() {
    getSomethingMethod(null, null, false, Collections.<String>emptyList());
  }

  private static List<String> getSomethingMethod(Object[] obj,
      String[] str, boolean flag, List<String> aList){ 
    System.out.println("I happen!");
    return aList;
  }
}

If the method itself gets invoked, we'll see I happen! . If it doesn't, we won't.

Then, I use this test class:

package org.test.stackoverflow;

import java.util.List;

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

@RunWith(PowerMockRunner.class)
@PrepareForTest(org.test.stackoverflow.StaticUtil.class)
public class StaticUtilTest {
  Object[] someObjectArray;
  String[] someStringArray;
  boolean aBoolean;
  List<String> someList;
  List<String> anotherList;

  @Test
  public void testWhenClassStringMethod() throws Exception {
    System.out.println("Beginning Test when(Class klass, String method name).doReturn(result)");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
    System.out.println("End Test when");
  }

  @Test
  public void testDoReturnActualMethod() throws Exception {
    PowerMockito.spy(StaticUtil.class);
    // This doesn't compile as you've correctly stated
//    PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod(someObjectArray, someStringArray, aBoolean, someList);
  }

  @Test
  public void testDoReturnClassStringMethod() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList);
    System.out.println("End Test doReturn");
  }
}

So, if it prints I happen , then we've used the wrong syntax. When I run this program, we get:

Beginning Test when(Class klass, String method name).doReturn(result)
I happen!
End Test when
Beginning Test doReturn().when(Class klass, String method name)
End Test doReturn

Therefore, you must use the syntax in the third test .

Note: this example uses static, empty arguments; obviously you should configure your example to use Argument Matchers as normal as appropriate for your application.

when you set the expectations on mock object, you have to use argument matchers like Matchers.any() or Matchers.anyString() but not actual arguments.

For more details, see my answer to J-Unit Test: Make static void method in final class throw exception

There is a potential issue with durron597's answer : the syntax in 'testDoReturnClassStringMethod' is not mocked properly. In that method, he tried to mock StaticUtil class but didn't call the test method wrapper. See the example

@Test
public void testDoReturnClassStringMethod() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList);
    StaticUtil.Wrapper();
    System.out.println("End Test doReturn");
}

The result for this is

Beginning Test doReturn().when(Class klass, String method name
I happen!
End Test doReturn

'I happen!' is printed. mock is not configured properly.

The correct way of mocking is:

@Test
public void testDoReturnWithProperMock() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", Matchers.anyObject(), Matchers.anyObject(), Matchers.anyBoolean(), Matchers.anyList());
    StaticUtil.Wrapper();
    System.out.println("End Test doReturn");

}

For which the result is:

Beginning Test doReturn().when(Class klass, String method name
End Test doReturn

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM