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

Spring Boot微服务JUnit测试PotentialStubbingProblem问题解决

Spring Boot微服务订单服务测试PotentialStubbingProblem错误解决

在Spring Boot微服务的订单服务中,运行OrderServiceImplTest类的test_When_Order_Success测试方法时遭遇PotentialStubbingProblem错误,报错显示RestTemplate的exchange方法存根参数与实际调用不匹配。

测试方法代码

@DisplayName("Get Order - Success Scenario")
@Test
void test_When_Order_Success() {

    String bearerToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew";

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.set("Authorization", "Bearer "+ bearerToken);

    HttpEntity request = new HttpEntity<>(headers);

    //Mocking
    Order order = getMockOrder();
    when(orderRepository.findById(anyLong()))
            .thenReturn(Optional.of(order));


    when(restTemplate.exchange(
            "http://PRODUCT-SERVICE/product/" + order.getProductId(),
            HttpMethod.GET, request, ProductResponse.class)).thenReturn(ResponseEntity.ok(getMockProductResponse()));

    when(restTemplate.exchange(
            "http://PAYMENT-SERVICE/payment/order/" + order.getId(),
            HttpMethod.GET, request, PaymentResponse.class)).thenReturn(ResponseEntity.ok(getMockPaymentResponse()));

    //Actual
    OrderResponse orderResponse = orderService.getOrderDetails(1,bearerToken);

    //Verification
    verify(orderRepository, times(1)).findById(anyLong());

    verify(restTemplate, times(1))
            .exchange("http://PRODUCT-SERVICE/product/" + order.getProductId(), HttpMethod.GET,
            request, ProductResponse.class);

    verify(restTemplate, times(1))
            .exchange("http://PAYMENT-SERVICE/payment/order/" + order.getId(), HttpMethod.GET,
            request, PaymentResponse.class);

    //Assert
    assertNotNull(orderResponse);
    assertEquals(order.getId(), orderResponse.getOrderId());
}

错误日志

02:28:15.051 [main] INFO com.microservice.orderservice.service.impl.OrderServiceImpl - OrderServiceImpl | getOrderDetails | Get order details for Order Id : 1
02:28:15.056 [main] INFO com.microservice.orderservice.service.impl.OrderServiceImpl - OrderServiceImpl | getOrderDetails | Invoking Product service to fetch the product for id: 1

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'exchange' method:
    restTemplate.exchange(
    "http://PRODUCT-SERVICE/product/1",
    GET,
    <[Content-Type:"application/json", Authorization:"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew"]>,
    class com.microservice.orderservice.payload.response.ProductResponse
);
    -> at com.microservice.orderservice.service.impl.OrderServiceImpl.getOrderDetails(OrderServiceImpl.java:113)
 - has following stubbing(s) with different arguments:
    1. restTemplate.exchange(
    "http://PRODUCT-SERVICE/product/1",
    GET,
    <[Content-Type:"application/json", Authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew"]>,
    class com.microservice.orderservice.payload.response.ProductResponse
);
      -> at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:71)
    2. restTemplate.exchange(
    "http://PAYMENT-SERVICE/payment/order/1",
    GET,
    <[Content-Type:"application/json", Authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew"]>,
    class com.microservice.orderservice.payload.response.PaymentResponse
);
      -> at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:75)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
    Please use 'will().given()' or 'doReturn().when()' API for stubbing.
  - stubbed method is intentionally invoked with different arguments by code under test
    Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.

    at com.microservice.orderservice.service.impl.OrderServiceImpl.getOrderDetails(OrderServiceImpl.java:113)
    at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:94)

原因分析

测试代码中给Authorization头添加了Bearer 前缀,但实际业务代码调用RestTemplate时未添加该前缀,导致Mockito存根的参数与实际调用的参数不匹配,触发Strict Stubbing的参数 mismatch 错误。

解决办法

方案1:修改测试代码,与业务代码保持一致

在测试代码中去掉Authorization头的Bearer 前缀,确保存根的HttpEntity和实际调用的完全一致:

// 原测试代码中的headers设置
// headers.set("Authorization", "Bearer "+ bearerToken);
// 修改为:
headers.set("Authorization", bearerToken);

对应的verify部分的request对象会自动匹配,无需额外修改。

方案2:修改业务代码,遵循OAuth2规范(推荐)

通常Authorization头的Bearer格式是标准规范,建议修改业务代码中构建HttpHeaders的逻辑,添加Bearer 前缀:

// 在OrderServiceImpl的getOrderDetails方法中,构建请求头时:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + bearerToken); // 添加前缀
HttpEntity request = new HttpEntity<>(headers);
// 然后调用restTemplate.exchange

修改后同步保持测试代码中的headers设置即可,确保存根与实际调用一致。

项目运行步骤

  • 启动服务注册中心(Eureka Server);
  • 启动配置中心;
  • 通过Docker启动Zipkin和Redis:
    docker run -d -p 9411:9411 openzipkin/zipkin
    docker run -d --name redis -p 6379:6379 redis
    
  • 启动API网关;
  • 启动其他服务。

内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:01:07