Powermock static final method in final class

Mandar Pandit picture Mandar Pandit · Jul 11, 2017 · Viewed 22.9k times · Source

The Test case I am writing for:

public class AClassUnderTest {

    // This test class has a method call
    public Long methodUnderTest() {

         // Uses the FinalUtilityClass which contains static final method
         FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>);

         // I want to mock above call so that test case for my "methodUnderTest" passes
    }
}

I have one final class.

public final class FinalUtilityClass {

   /**
    * Method has 3 parameters
    */
   public static final MyBean myStaticFinalMethod(<3-parameters-here>) {

   }
}

I have already added below code in my test class:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ FinalUtilityClass.class })

I want to write test case for mocking it. I want to mock the call of myStaticFinalMethod() so that I can get the expected MyBean instatnce which I can use in further code to pass my test case.

The <3-parameters-here> are Calendar, String, String.

I tried doing:

1)

PowerMockito.mock(FinalUtilityClass.class)
PowerMockito.when(FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>).thenReturn(new MyBean());

2)

PowerMockito.mockStatic(FinalUtilityClass.class)
PowerMockito.when(FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>).thenReturn(new MyBean());

3)

PowerMockito.spy(FinalUtilityClass.class)
PowerMockito.when(FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>).thenReturn(new MyBean());

But nothing worked for me. Please suggest what is correct way for mocking static final method in final class.

Answer

GhostCat picture GhostCat · Jul 11, 2017

The following steps are required to mock calls to static methods:

  • Use the @RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
  • Use the @PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case
  • Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class

When you follow these steps as documented, your tests should work. And as the OP seems to be confused about PowerMock vs. PowerMockito - that is (more or less) the same thing:

PowerMock and PowerMockito are based on the same technology. They just have different "connectors" to either work with EasyMock or Mockito. So, yes the above example says PowerMock.mockStatic() - but PowerMockito has mockStatic() methods as well. In that sense: the core things (for example regarding preparation with annotations) are the same. See here for example (they are so close that the linked tutorial says "Intro to PowerMock" - although it does introduce PowerMockito.

And as you seem to not believe me - see this example:

package ghostcat.test;

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

final class ClassWithStatic {
    public final static int ignoreMethodCall(String a, String b, int c) {
        System.out.println("SHOULD NOT SHOW UP: " + a);
        return c;
    }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStatic.class)
public class MockStaticTest {
    @Test
    public void test() {
        PowerMockito.mockStatic(ClassWithStatic.class);
        PowerMockito.when(ClassWithStatic.ignoreMethodCall("a", "b", 5)).thenReturn(42);
        org.junit.Assert.assertEquals(ClassWithStatic.ignoreMethodCall("a", "b", 5), 42);
    }
}

This test passes; and doesn't print anything. Therefore the final static method gets mocked.