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

使用RestTemplate时出现PotentialStubbingProblem存根参数不匹配问题

RestTemplate exchange()方法Mockito测试存根参数不匹配问题

我在应用中使用RestTemplate的exchange()方法调用外部API,编写JUnit和Mockito测试用例时遇到了存根参数不匹配异常,尝试过lenient()方法但问题仍未解决。

业务代码

@Service
public class ApiService {

  @Autowired
  private RestTemplate restTemplate;
  
  @Value("{url}")
  private String url;
  
  public TrackResponse getTpiValue(TrackRequest trackRequest){
  
    TrackResponse trackResponse = null;
    
    HttpHeaders headers = new HttpHeaders();
    
    HttpEntity<TrackRequest> entity = new HttpEntity<TrackRequest>(trackRequest, headers);
    
    ResponseEntity<TrackResponse> response = restTemplate.exchange(url, HttpMethod.Post, entity, TrackResponse.class);
    
    if(response.getStatusCode == HttpStatus.ok){
       trackResponse = response.getBody();
    }
  return trackResponse;
  }

}

测试用例代码

@TestInstance(Lifecycle.PER_CLASS)
@ExtendWith(MocikotExtension.class)
public class ApiServiceTest {

  @Mock
  private RestTemplate restTemplate;
  
  @InjectMocks
  private ApiService apiService;
    
  public void getTpiValueTest(){
  
    TrackRequest trackRequest = new TrackRequest();
    trackRequest.setId("UTHL10");
    
    TrackResponse trackResponse = new TrackResponse();
    trackResponse.setTrackId("QWEDRTHFDS");
    
    ResponseEntity<TrackResponse> response = new ResponseEntity<>(trackResponse, HttpStatus.ok);
    
    when(restTemplate.exchange(eq(null), eq(HttpMethod.Post), any(HttpEntity.class), eq(TrackResponse.class))).thenReturn(response);
    
    TrackResponse finalResponse = apiService.getTpiValue(trackRequest);
    
    assetEquals(response.getbody(), finalResponse.getTrackId());
  }

}

报错信息

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'exchange' method:
    restTemplate.exchange(
    null,
    POST,
    <com.application.track.TrackRequest@3c486eb1,[]>,
    class com.application.track.TrackResponse
);
    -> at com.application.track.ApiService.getTpiValue(ApiService.java:18)
 - has following stubbing(s) with different arguments:
    1. restTemplate.exchange(
    null,
    null,
    null,
    null
);
-> at com.application.track.ApiServiceTest.getTpiValueTest(ApiServiceTest.java:21)

问题分析与修复方案

1. 测试类注解拼写错误

@ExtendWith(MocikotExtension.class) 中的 MocikotExtension 是拼写错误,正确应为 MockitoExtension。这个错误会导致Mockito无法正确初始化Mock对象,是参数匹配异常的核心原因之一。

2. 静态导入缺失

测试用例中使用了eq()、any()等匹配器,但如果没有静态导入org.mockito.ArgumentMatchers.*,Mockito会将这些方法调用视为普通对象而非匹配器,导致存根参数匹配失效,出现null参数的存根记录。

3. 测试方法缺少@Test注解

当前测试方法getTpiValueTest()没有添加@Test注解,JUnit不会执行该测试方法,修正后才能触发测试逻辑。

4. 断言逻辑错误

原断言assetEquals(response.getbody(), finalResponse.getTrackId())存在两处错误:

  • assetEquals应为assertEquals
  • response.getbody()是TrackResponse对象,finalResponse.getTrackId()是字符串,类型不匹配,应改为比较两者的trackId属性

5. 业务代码小问题(可选修复)

业务代码中@Value("{url}")缺少$符号,正确应为@Value("${url}");HttpMethod.Post应为HttpMethod.POST,response.getStatusCode == HttpStatus.ok应为response.getStatusCode() == HttpStatus.OK(注意方法调用和大写常量)。

修复后的测试用例代码

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

@TestInstance(Lifecycle.PER_CLASS)
@ExtendWith(MockitoExtension.class)
public class ApiServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private ApiService apiService;

    @Test
    public void getTpiValueTest() {
        // 准备测试数据
        TrackRequest trackRequest = new TrackRequest();
        trackRequest.setId("UTHL10");

        TrackResponse trackResponse = new TrackResponse();
        trackResponse.setTrackId("QWEDRTHFDS");

        ResponseEntity<TrackResponse> mockResponse = new ResponseEntity<>(trackResponse, HttpStatus.OK);

        // 正确存根RestTemplate的exchange方法
        when(restTemplate.exchange(
                eq(null), // 对应业务代码中未注入的url
                eq(HttpMethod.POST),
                any(HttpEntity.class),
                eq(TrackResponse.class)
        )).thenReturn(mockResponse);

        // 执行测试方法
        TrackResponse finalResponse = apiService.getTpiValue(trackRequest);

        // 断言结果
        assertEquals(mockResponse.getBody().getTrackId(), finalResponse.getTrackId());
    }
}

内容的提问来源于stack exchange,提问作者Rahul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:20:58