Spring Boot JUnit5 Mockito when-thenReturn失效致NPE问题
问题分析与解决方案
核心问题
当控制器中token赋值为空字符串""时,Mockito的Stub未生效,clusterService.startPatchingTest()返回默认值null,导致调用result.toLowerCase()触发空指针异常(NPE);但将token改为null时测试正常通过。
原因
Mockito的anyString()匹配器存在行为限制:仅匹配非null的字符串(包括空字符串""),但部分旧版本Mockito中anyString()会匹配null,这就导致了测试出现看似矛盾的现象:
- 当
token = null时,若你的Mockito版本兼容null匹配,Stub生效返回"OK",测试通过; - 当
token = ""时,理论上anyString()应匹配空字符串,但可能因参数匹配的细节差异(如对象实例匹配逻辑、Mockito版本兼容问题)导致Stub未触发,返回null引发NPE。
解决方案
1. 修改Mockito匹配器,兼容null与空字符串
将测试中第三个参数的anyString()替换为any(String.class)或nullable(String.class),这两个匹配器可以兼容null和任意字符串(包括空字符串):
// 方案1:使用any(String.class)匹配任意String类型对象(含null) when(clusterService.startPatchingTest(any(), anyString(), any(String.class), anyString())).thenReturn("OK"); // 方案2:使用nullable(String.class)明确匹配可空的String参数 when(clusterService.startPatchingTest(any(), anyString(), nullable(String.class), anyString())).thenReturn("OK");
2. 控制器中增加null安全校验
即使Stub生效,也要避免业务代码因result为null触发NPE,在控制器中添加null检查:
@PostMapping("/patch/clustertest/{clustername}/host/{hostname}") public ResponseEntity<?> patchClusterTestVM(@PathVariable("clustername") String clusterName, @PathVariable("hostname") String hostName) { String token = ""; String uuid = UUID.randomUUID().toString(); String result = clusterService.startPatchingTest(new ClusterDetailsClass(1L, "mycluster"), hostName, token, uuid); // 增加null校验,避免NPE if (result == null) { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } return new ResponseEntity<>(result.toLowerCase(), HttpStatus.OK); }
内容的提问来源于stack exchange,提问作者Zeeshan
相关产品推荐
相关产品推荐

