SpringBoot测试中Mockito mock RestTemplate的postForEntity方法报错求解
问题根因
你当前的Mock逻辑存在3个核心错误,导致打桩不生效:
- 未覆盖token生成接口的Mock:业务代码执行
getEvementsReleves时会优先调用generateRemoteToken方法获取token,该方法内调用了postForEntity请求token接口,但你完全没有对这个调用打桩,仅Mock了业务数据接口的调用。 - 方法匹配错误:业务数据接口的调用用的是
exchange+HttpMethod.GET,但你后续调整时错误地打了postForEntity的桩,方法签名完全不匹配。 - 参数匹配失效:你用了精确对象匹配来设置打桩规则,但业务代码里生成的
URI、HttpEntity和测试代码里new的对象不是同一个实例,Mockito默认的equals匹配会直接失败,导致打桩规则不触发。 - 多余的Spy调用:
@Mock已经生成了Mock对象,不需要再调用Mockito.spy(restTemplate),属于无效逻辑。
修复方案
1. 补全token接口的打桩逻辑
在@Before方法中实现你预留的initAuthentificationMock方法,Mock token生成接口的调用:
private void initAuthentificationMock() { // 构造符合oauth2返回格式的mock响应 String mockTokenResp = "{\"access_token\": \"" + MOCKED_TOKEN_VALUE + "\"}"; ResponseEntity<String> tokenResp = new ResponseEntity<>(mockTokenResp, HttpStatus.OK); // 用Mockito参数匹配器匹配所有postForEntity调用,避免实例匹配失效 Mockito.doReturn(tokenResp).when(restTemplate) .postForEntity( ArgumentMatchers.any(URI.class), ArgumentMatchers.any(HttpEntity.class), ArgumentMatchers.eq(String.class) ); }
同时删除beforeEach方法里的Mockito.spy(restTemplate)行。
2. 修正业务数据接口的打桩逻辑
把initEvementsRelevesMock里的打桩代码改为匹配exchange方法调用:
ResponseEntity<String> mockedResponse = new ResponseEntity<>(json, HttpStatus.OK); Mockito.doReturn(mockedResponse).when(restTemplate) .exchange( ArgumentMatchers.anyString(), ArgumentMatchers.eq(HttpMethod.GET), ArgumentMatchers.any(HttpEntity.class), ArgumentMatchers.eq(EnergyV1ConsumptionReading[].class) );
补充说明
如果需要更精确的参数匹配,可以把any(URI.class)/anyString()替换为eq(你的目标URI/URL),只要保证参数值和业务代码生成的一致即可。
内容的提问来源于stack exchange,提问作者Adrien Ruffié
相关产品推荐
相关产品推荐

