4

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

Community
  • 1
  • 1
user3897392
  • 397
  • 2
  • 5
  • 22

2 Answers2

8

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.

Community
  • 1
  • 1
durron597
  • 31,968
  • 17
  • 99
  • 158
  • Thanks so much for the detailed answer, I spent such a long time on this! The syntax in the third test worked perfectly. THANK YOU THANK YOU THANK YOU! – user3897392 Aug 04 '15 at 14:49
  • How the third test worked ?. 'I happen!' string is not printed, it doesn't mean the mocking is configured properly. here you tried to mock StaticUtil class but you didn't call the test method wrapper. see my another answer. – kswaughs Aug 05 '15 at 07:11
-3

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
Community
  • 1
  • 1
kswaughs
  • 2,967
  • 1
  • 17
  • 21
  • down voter, please update the reason for downvoting the correct answer – kswaughs Aug 05 '15 at 07:12
  • 3
    This is a borderline link-only answer. You should expand your answer to include as much information here, and use the link only for reference. – Kyll Aug 05 '15 at 13:41
  • 1
    It's a link-only answer to another SO question that @kswaughs answered. Either the relevant information should be ported here, or this question should be marked as a duplicate of the linked question. – dcsohl Aug 05 '15 at 15:48
  • 3
    @kswaughs You posted this answer first, but then posted a 2nd answer. You could have edited this (1st) answer and added your additional information. See the "edit" link under your answer. Your link is also just another answer on Stack Overflow, and if that answers this question perhaps this is a duplicate? See this question: [What do we do with answers that are just links to other Stack Overflow answers?](http://meta.stackexchange.com/questions/100532/what-do-we-do-with-answers-that-are-just-links-to-other-stack-overflow-answers) :) – James Aug 05 '15 at 16:02