Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powermock static final method in final class

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.

like image 555
Mandar Pandit Avatar asked Jul 11 '17 12:07

Mandar Pandit


People also ask

Can PowerMock mock final classes?

Using PowerMockito to Mock Final and Static Methods in Java Unit Testing. This document presents two Maven example projects for mocking final and static methods using PowerMockito for Java unit testing.

Can final class have static methods?

Oh yes you can. The data belongs to the Class object, StackOverflow . Any object that can access your StackOverflow Class and has access to its methods can get your data, no matter where it is in your project. Static fields are a kind of global data.

Can we mock final methods using Mockito?

Configure Mockito for Final Methods and ClassesBefore we can use Mockito for mocking final classes and methods, we have to configure it. Mockito checks the extensions directory for configuration files when it is loaded. This file enables the mocking of final methods and classes.

How do you make a mock object of the final class?

After you created this file, Mockito will automatically use this new engine and one can do : final class FinalClass { final String finalMethod() { return "something"; } } FinalClass concrete = new FinalClass(); FinalClass mock = mock(FinalClass. class); given(mock.


1 Answers

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.

like image 57
GhostCat Avatar answered Sep 30 '22 15:09

GhostCat