Mockito模拟RestTemplate.exchange始终返回null问题求助
解决Mockito模拟RestTemplate.exchange始终返回null的问题
这个问题我之前也碰到过,大概率是参数匹配器没正确匹配到ParameterizedTypeReference或者mock的RestTemplate实例没注入到目标类导致的,咱们一步步排查解决:
1. 先确认RestTemplate的实例是否正确注入
很多时候mock失效都是因为目标类里用的不是咱们mock的那个RestTemplate对象:
- 如果是Spring Boot测试,确保用
@MockBean把mock的RestTemplate注入到Spring容器; - 如果是普通单元测试,用
@InjectMocks把mock的RestTemplate注入到被测试类里,同时被测试类里的RestTemplate字段不能是final的,否则无法注入。
比如标准的测试类结构应该是这样的:
@ExtendWith(MockitoExtension.class) public class LovServiceTest { @Mock private RestTemplate restTemplate; @InjectMocks private LovService lovService; // 这是调用restTemplate.exchange的业务类 // ...测试方法 }
2. 修正ParameterizedTypeReference的匹配逻辑
ParameterizedTypeReference是一个抽象类,直接用any()有时候会因为泛型类型擦除导致匹配失败,你可以换两种方式来匹配:
方式一:用argThat匹配类型
通过argThat来判断传入的ParameterizedTypeReference的实际类型是否和你代码里的一致:
// 准备mock数据 List<LOV> mockLovList = Arrays.asList(new LOV(), new LOV()); ResponseEntity<List<LOV>> mockResponse = new ResponseEntity<>(mockLovList, HttpStatus.ACCEPTED); // 修正mock匹配逻辑 Mockito.when(restTemplate.exchange( anyString(), eq(HttpMethod.GET), isNull(), // 匹配第三个参数为null argThat(typeRef -> { // 对比类型是否一致 Type expectedType = new ParameterizedTypeReference<List<LOV>>() {}.getType(); return expectedType.equals(typeRef.getType()); }) )).thenReturn(mockResponse);
方式二:直接匹配具体的实例(如果代码里的ParameterizedTypeReference是固定实例)
如果你的业务代码里ParameterizedTypeReference是复用的同一个实例,比如:
// 业务类里定义的固定实例 private static final ParameterizedTypeReference<List<LOV>> LOV_LIST_TYPE = new ParameterizedTypeReference<>() {}; // 调用时用这个实例 ResponseEntity<List<LOV>> response = restTemplate.exchange(url, GET, null, LOV_LIST_TYPE);
那mock的时候就可以直接用eq(LOV_LIST_TYPE)来匹配,这样精准度更高:
Mockito.when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), isNull(), eq(LOV_LIST_TYPE))) .thenReturn(mockResponse);
3. 验证方法是否被调用(排查问题的关键)
如果上面的方法都没用,先验证restTemplate.exchange是否真的被调用了,添加这段代码到测试方法末尾:
Mockito.verify(restTemplate, times(1)) .exchange(anyString(), eq(HttpMethod.GET), isNull(), any(ParameterizedTypeReference.class));
- 如果抛出
Wanted but not invoked异常:说明业务代码里根本没用到你mock的RestTemplate,回到第一步检查注入问题; - 如果验证通过但还是返回null:说明参数匹配器还是没匹配上,换上面的方式二来匹配。
内容的提问来源于stack exchange,提问作者avi
相关产品推荐
相关产品推荐

