在WebMvcTest中显示为null的模拟组件



我正在测试一个控制器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

最新更新