You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:02:54