Alessandro Argentieri
Alessandro Argentieri

Reputation: 3215

Spring boot mocking static methods with PowerMock in Integration test

I'm writing integration test on a RestController in SpringBoot. Normally I would run with SpringRunner.class, but when it comes to Mock a static method I need to use PowerMock.

The strange fact is that when I run the single tests, they individually pass (but returns error messages), when I try to run the entire test class, no test passes and it returns the same error message.

@RunWith(PowerMockRunner.class)
@PrepareForTest({JwtUtils.class})
//@PowerMockRunnerDelegate(SpringRunner.class) THIS DOESN'T WORK!!!
@SpringBootTest(classes = SpringBootJwtApplication.class)
public class RestAccessIntegrationTest {

  @Autowired @InjectMocks
  RestController restController;

  @Mock
  HttpServletRequest request;

  @Test
  public void operationsPerAccountWhenSuccessfulTest(){
    mockStatic(JwtUtils.class);
    when(JwtUtils.myMethod(request)).thenReturn("blabla");
    String expected = ... ;
    String actual = restController.getOperations();
    assertEquals(actual, expected);
  }

}

If I run the test or the entire class I get an error of this type:

Exception in thread "main" java.lang.NoSuchMethodError: org.powermock.core.MockRepository.addAfterMethodRunner(Ljava/lang/Runnable;)at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:50)

If I uncomment @PowerMockRunnerDelegate(SpringRunner.class) there it comes this other error:

Exception in thread "main" java.lang.NoClassDefFoundError: org/powermock/core/testlisteners/GlobalNotificationBuildSupport$Callback at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:139)

Upvotes: 3

Views: 13132

Answers (2)

Alessandro Argentieri
Alessandro Argentieri

Reputation: 3215

It was due to incompatibility in library version of PowerMock and Mockito. I suggest to check the compatibility version table provided by PowerMock team or to switch to JMockit to mock static and private methods.

Upvotes: 1

Indra Basak
Indra Basak

Reputation: 7394

In the when method, try using any(HttpServletRequest.class) instead of the request mock object. Also use MockHttpServletRequest instead of mocking HttpServletRequest. This should work,

@RunWith(PowerMockRunner.class)
@PrepareForTest(JwtUtils.class)
@PowerMockIgnore( {"javax.management.*"})
public class RestAccessIntegrationTest {

    @InjectMocks
    private RestController restController;

    private MockHttpServletRequest request;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        request = new MockHttpServletRequest();
        RequestContextHolder.setRequestAttributes(
                new ServletRequestAttributes(request));
    }

    @Test
    public void operationsPerAccountWhenSuccessfulTest() {
        mockStatic(JwtUtils.class);
        when(JwtUtils.myMethod(any(HttpServletRequest.class)))
           .thenReturn("blabla");

        String expected = ... ;
        // does your getOperations take HttpServletRequest
        // as parameter, then controller.getOperations(request);
        String actual = restController.getOperations();
        assertEquals(actual, expected);
    }
}

Upvotes: 2

Related Questions