Mock RestTemplate exchange方法返回null问题求助
问题:Mock RestTemplate#exchange始终返回null
我参考了多篇相关技术帖子,尝试多种方式Mock RestTemplate#exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) 方法(未传入uriVariables),但始终无法获取非空返回值。
业务源码(简化后)
Request request = new Request(); request.setDataId(1); String query = "query ($ request:Request!)" + "{" + " fetchData(request:$request)" + " {" + " planId" + " }" + " }"; RequestBody requestBody = new RequestBody(query, Collections.singletonMap("request", request)); HttpEntity<RequestBody> requestEntity = new HttpEntity<>(requestBody, createHttpHeaders()); return restTemplate.exchange("http://localhost:8080/gql", HttpMethod.POST, requestEntity, JsonNode.class); private HttpHeaders createHttpHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); return headers; }
RequestBody类(使用Lombok)
@Getter @AllArgsConstructor public class RequestBody implements Serializable { private static final long serialVersionUID = -203524485553511477L; private String query; private Map<String,Object> variables; }
测试代码
@Mock private RestTemplate restTemplate; @Mock private ObjectMapper objectMapper; @InjectMocks private FetchDataService fetchDataService; @Test public void testFetchData() throws IOException { String json = new String(Files.readAllBytes(Paths.get("src/test/resources/Data.json"))); ObjectMapper testMapper = new ObjectMapper(); JsonNode expectedResponse = testMapper.readTree(json); when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class))) .thenReturn(new ResponseEntity<>(expectedResponse, HttpStatus.OK)); ResponseEntity<JsonNode> response = fetchDataService.getData(); }
上述代码中expectedResponse是JsonNode实例,但response的body始终为null。我已通过以下代码验证调用确实发生:
Mockito.verify(restTemplate) .exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class));
环境:JUnit 5、Spring Boot 2.6.7、JDK 11
解决方案
1. 匹配正确的exchange重载方法
你Mock的是4参数的exchange方法,但实际调用的是5参数(最后一个为可变参数Object... uriVariables)的重载版本。不传可变参数时,Java会默认传递空数组,因此需要Mock对应重载方法:
when(restTemplate.exchange( anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class), any(Object[].class) // 匹配可变参数 )).thenReturn(new ResponseEntity<>(expectedResponse, HttpStatus.OK));
或简化为:
when(restTemplate.exchange( anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class), any() )).thenReturn(new ResponseEntity<>(expectedResponse, HttpStatus.OK));
2. 确保Mock初始化正确
测试类需添加@ExtendWith(MockitoExtension.class)(JUnit 5),否则@Mock和@InjectMocks无法完成初始化:
@ExtendWith(MockitoExtension.class) public class FetchDataServiceTest { // ... 测试代码 }
3. 验证expectedResponse有效性
确认Data.json路径正确、内容为合法JSON,可在测试中添加断言:
assertNotNull(expectedResponse, "预期响应JSON不能为空");
4. 修复业务源码变量冲突
业务代码中Request request与HttpEntity<RequestBody> request重名,建议重命名为requestEntity避免潜在逻辑问题:
HttpEntity<RequestBody> requestEntity = new HttpEntity<>(requestBody, createHttpHeaders()); return restTemplate.exchange("http://localhost:8080/gql", HttpMethod.POST, requestEntity, JsonNode.class);
内容的提问来源于stack exchange,提问作者linuxNoob
相关产品推荐
相关产品推荐

