如何使用Mockito正确mock RestTemplate.postForEntity避免空指针异常
Mock失效空指针的具体原因
Mockito的桩代码(stub)严格按照方法签名+参数匹配规则命中,你的问题核心是桩代码匹配的方法和实际业务调用的方法不是同一个重载:
- 写桩代码时你用
anyString()作为第一个参数的匹配器,只会命中第一个入参是String类型的postForEntity重载,该重载完整签名为public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) - 实际业务代码运行时,传入
postForEntity的第一个参数是URI类型(要么定义的url变量实际类型是URI,要么代码中做了隐式/显式类型转换),最终调用的是你排查到的public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType)重载 - 这个URI参数的重载没有配置任何桩逻辑,Mockito对于未配置桩的非void方法,默认返回值是
null,因此拿到的ResponseEntity<String> result是null,后续调用result.getBody()直接触发空指针,预设的返回值自然不会生效。
修复方式
任选一种即可:
- 如果业务代码确实传URI类型的url,修改桩代码的第一个参数匹配器为URI类型:
when(restTemplate.postForEntity(any(URI.class), any(), eq(String.class))) .thenReturn(new ResponseEntity<>("5be9b7f2b7c", HttpStatus.OK));
- 如果不想纠结参数类型、避免重载匹配偏差,可以直接用通用类型匹配器兜底,只要后两个参数类型符合就命中桩逻辑,兼容性最好:
when(restTemplate.postForEntity(any(), any(), eq(String.class))) .thenReturn(new ResponseEntity<>("5be9b7f2b7c", HttpStatus.OK));
补充:如果确认业务代码传的是String类型url,还要注意String参数版本的
postForEntity带可变参数uriVariables,用严格参数匹配容易漏匹配可变参数,通用any()匹配的写法更稳妥。
内容的提问来源于stack exchange,提问作者JLo
相关产品推荐
相关产品推荐

