Mockito测试中ResponseEntity为空空指针问题的排查与解决咨询
问题:Mockito模拟RestTemplate后仍出现ResponseEntity空指针异常
编写Mockito测试用例时,明明已经对RestTemplate的exchange方法进行模拟,但还是出现ResponseEntity为空的NullPointerException,错误信息如下:
java.lang.NullPointerException: Cannot invoke "org.springframework.http.ResponseEntity.getBody()" because "responseEntity" is null
模拟代码
Mockito.when(restTemplate.exchange(ArgumentMatchers.anyString(), Mockito.any(HttpMethod.class), ArgumentMatchers.any(), ArgumentMatchers.<Class<byte[]>>any())) .thenReturn(new ResponseEntity("test".getBytes(), HttpStatus.OK));
业务方法代码
public void getLetters() { try { List<letters> records = letterRepository.getletters(); HttpHeaders headers = httpClientToken.getHeader( tokenurl, Client, Secret, Granttype ); ResponseEntity<byte[]> responseEntity; HttpEntity<?> entity = new HttpEntity<>(headers); for(int i = 0; i < records.size(); i++) { String Url = "http://localhost:8080/documents/getdocument"; URI uri = UriComponentsBuilder.fromHttpUrl(Objects.requireNonNull(Url)) .queryParam("spaceId", records.get(i).letterId) .build() .toUri(); try { responseEntity = restTemplate.getTemplateAttributesRestTemplate().exchange(uri, HttpMethod.GET, entity, byte[].class); InputStream anyInputStream = new ByteArrayInputStream(responseEntity.getBody()); str = "C:\\Users\\hm\\Downloads\\letter.pdf"; OutputStream outputStream = new FileOutputStream(str); copyFile(anyInputStream, outputStream, 1024 * 1024 * 10); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } }
错误原因
- 模拟的RestTemplate实例不匹配:业务代码中调用的是
restTemplate.getTemplateAttributesRestTemplate()返回的RestTemplate对象,而你模拟的是外层的restTemplate实例,两者不是同一个对象,导致模拟未生效。 - 方法签名不匹配:你模拟的是接收
String类型URL的exchange重载方法,但业务代码中调用的是接收URI类型参数的重载方法,参数类型不匹配,模拟的方法逻辑不会被触发,因此返回null。
解决方法
确保模拟目标实例正确
- 如果
getTemplateAttributesRestTemplate()是当前类的方法,需要额外模拟这个方法,让它返回你已经设置好模拟逻辑的RestTemplate实例:Mockito.when(restTemplate.getTemplateAttributesRestTemplate()).thenReturn(yourMockRestTemplate); - 或者直接确保业务代码中使用的RestTemplate就是你注入的mock实例,避免多层调用导致实例不一致。
- 如果
修正模拟的方法签名
修改模拟代码,匹配接收URI参数的exchange重载方法:Mockito.when(yourMockRestTemplate.exchange(ArgumentMatchers.any(URI.class), Mockito.any(HttpMethod.class), ArgumentMatchers.any(), ArgumentMatchers.<Class<byte[]>>any())) .thenReturn(new ResponseEntity("test".getBytes(), HttpStatus.OK));补充测试前置条件
确保letterRepository.getletters()返回非空列表,这样循环才能执行到exchange调用的逻辑,否则测试无法覆盖到报错代码段。
内容的提问来源于stack exchange,提问作者Hareni
相关产品推荐
相关产品推荐

