Spring 在集成测试中使用 PowerMock 启动模拟静态方法

Spring boot mocking static methods with PowerMock in Integration test

我正在 SpringBoot 中的 RestController 上编写集成测试。 通常我会 运行 和 SpringRunner.class,但是当涉及到模拟静态方法时,我需要使用 PowerMock。

奇怪的是,当我 运行 单个测试时,它们单独通过(但 returns 错误消息),当我尝试 运行 整个测试时 class,没有测试通过,它 returns 相同的错误消息。

@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);
  }

}

如果我 运行 测试或整个 class 我得到这种类型的错误:

线程 "main" java.lang.NoSuchMethodError 中的异常:org.powermock.core.MockRepository.addAfterMethodRunner(Ljava/lang/Runnable;)在 org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:50)

如果我取消对@PowerMockRunnerDelegate(SpringRunner.class) 的注释,就会出现另一个错误:

线程中出现异常 "main" java.lang.NoClassDefFoundError: org/powermock/core/testlisteners/GlobalNotificationBuildSupport$Callback 在 org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:139)

when 方法中,尝试使用 any(HttpServletRequest.class) 而不是 request 模拟对象。还使用 MockHttpServletRequest 而不是模拟 HttpServletRequest。这应该有效,

@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);
    }
}

这是由于 PowerMock 和 Mockito 的库版本不兼容。我建议检查 PowerMock 团队提供的兼容性版本 table 或切换到 JMockit 以模拟静态和私有方法。