Thursday, May 3, 2018

PowerMockito - Mocking One Static Method and Not Mocking Other in the Same Class

Suppose we have a class,

  public class ClassWithPrivateStaticMethods {
  
   private static String getParam(String paramName) {
      String result = "";

      ...
      ...

      return result;
   }

   private static String getDetail(String contextName) {
      String result = "";

      String temp = getParam(tempParamName);
      ...

      return result;
   }
}

Until today, to mock static method, I had been doing:

  PowerMockito.mockStatic(ClassWithPrivateStaticMethods.class);
  PowerMockito.when(ClassWithPrivateStaticMethods.class, "getParam", Mockito.anyString()).thenReturn("dummy");

This works only when your test executes only this static method getParam().

Problem

PowerMockito.mockStatic() actually mocks all the static method in the class.

So if you have the circumstance where you want to mock one static method, but you want other method to run normally, then this method will not work. Because the other method will also be mocked.

  PowerMockito.mockStatic(ClassWithPrivateStaticMethods.class)
  PowerMockito.when(ClassWithPrivateStaticMethods.class, "getParam", Mockito.anyString()).thenReturn("dummy");
  String result = Whitebox.invokeMethod(ClassWithPrivateStaticMethods.class, "getDetail", Mockito.anyString());

here result will not the result of the execution of the method getDetail() but result of mocked up which is either null or equivalent because we haven't defined mock for the method getDetail

Solution - Partial Mocking

We can solve this by mocking individual static methods by following way:

  PowerMockito.spy(ClassWithPrivateStaticMethods.class);
  PowerMockito.doReturn("dummy").when(ClassWithPrivateStaticMethods.class, "getParam", Mockito.anyString())
  String finalResult = Whitebox.invokeMethod(ClassWithPrivateStaticMethods.class, "getDetail", Mockito.anyString());

Complete Code Demonstration

Following is a complete code demonstration.







No comments:

Post a Comment