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 以模拟静态和私有方法。
我正在 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 以模拟静态和私有方法。