我正在测试一个控制器JmxController
,它调用一个服务JmxService
,后者又调用一个组件CrfVerifier
。不幸的是,该组件抛出了一个NPE,尽管事实上我已经嘲笑过它。
JmxControllerTest.java
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = JmxController.class, secure = false)
public class JmxControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private JmxControlToolService jmxControlToolService;
@MockBean
private JmxControlService jmxControlService;
@MockBean
private CrfVerifier crfVerifier;
@Test
public void shouldThrowInvalidCrfExceptionForJmxOperationWhenCrfInvalidAndOperationIsCritical() throws Exception {
//when
when(jmxControlToolService.getJmxOperationsAndAttributes(anyString(), anyString(), anyString(), anyString())).thenReturn(buildOperationsAndAttributesList());
when(jmxControlToolService.executeOperation(any())).thenCallRealMethod();
doNothing().when(crfVerifier).verifyCrf(anyString(), anyString());
//then
mockMvc.perform(post("/jmx/execute-jmx-operation")
.etc()
}
JmxController.java
@PostMapping("/execute-jmx-operation")
public JmxOperationResponseDto executeJmxOperation(@RequestBody JmxOperation jmxOperation) {
return jmxControlToolService.executeOperation(jmxOperation);
}
JmxServce.java
public JmxResposneDto executeOperation(JmxDto jmxDto) {
...
crfVerifier.verifyCrf(jmxExecutedOperationDto.getCrfNumber(), jmxDto.getApplication()); //NPE on crfVerifier
...
}
CrfVerifier.java
@Component
@RequiredArgsConstructor
@Slf4j
public class CrfVerifier {
private final ServiceNowRestClient serviceNowRestClient;
public void verifyCrf(String str1, String str2) {
...
}
我已经尝试在类上使用@TestConfiguration
和@Import
,但在JmxService中仍然得到了NPE。
我不明白为什么被嘲笑的服务没有抛出NPE,而被嘲笑的组件却抛出了。有人能告诉我决议的方向吗?
我尝试过在类上使用@TestConfiguration和@Import但我还是在JmxService获得了NPE。
您的JmxControllerTest
模拟类型为JmxControlService
的bean。由于它被定义为mock,模拟beanCrfVerifier
不会注入仿真beanJmxControlService
中。Moked bean不像普通Spring bean那样构造;它们仅仅被添加到TestApplicationContext中作为";"空";可以在其上定义测试逻辑的bean。
在测试中,您指出当调用jmxControlToolService.executeOperation
时,应该调用实际的方法,而不是依赖于模拟行为:
when(jmxControlToolService.executeOperation(any())).thenCallRealMethod();
但是,由于该方法需要crfVerifier
的实例,因此会引发NullPointerException。
我建议在JmxControlService
上使用@SpyBean
,或者调整测试范围。例如,如果测试的目的是测试JmxController
控制器和JmxControlToolService
之间的交互,则可以模拟服务而不是服务本身所需的beans。