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

Spring Boot中RestTemplate跨服务请求测试编写及URI报错解决

RestTemplate Mock测试异常修复方案

异常根因

你遇到的java.lang.IllegalArgumentException: URI is required异常本质是Mockito打桩未命中,执行了真实RestTemplate的方法逻辑触发的,具体有三个错误点:

  • Mock初始化错误:被@Mock、@InjectMocks注解标注的对象不需要手动实例化,且未启用Mockito注解支持,导致Mock代理对象未生效
  • 重载匹配错误:postForEntity存在多个重载方法,直接写Mockito.any()没有指定匹配类型,无法正确匹配你业务代码中调用的重载,打桩规则失效
  • 参数匹配失败:打桩时第二个参数直接传入实时生成的请求对象,若业务代码中生成的请求对象和该对象不满足equals匹配规则,也会导致打桩未命中

修复方案

1. 修正测试类Mock初始化规则

启用Mockito注解支持,移除Mock对象的手动实例化逻辑:

  • Junit4 增加@RunWith(MockitoJUnitRunner.class)注解
  • Junit5 增加@ExtendWith(MockitoExtension.class)注解

2. 修正打桩匹配规则

明确指定每个参数的匹配器:

  • 第一个URI参数:如果业务代码传的是字符串URI就用anyString(),如果是URI类型对象就用any(URI.class),明确匹配重载
  • 第二个请求体参数:如果需要精确匹配请求体就用eq()包装你构造的预期请求对象,不需要精确匹配直接用any()
  • 第三个响应类型参数:用eq()包装ChargeResponse.class
    注意:Mockito规则要求只要有一个参数使用了匹配器,所有参数都必须使用匹配器,字面量值必须用eq()包装

完整可运行测试代码

// Junit5 版本注解,Junit4换成@RunWith(MockitoJUnitRunner.class)
@ExtendWith(MockitoExtension.class)
class ServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private RConsumerService refundConsumerService;

    @Test
    public void sendRequestToBillingService(){
        // 构造模拟响应
        ChargeResponse chargeResponse = new ChargeResponse();
        chargeResponse.setInstanceKey("testInstanceKey");

        // 构造入参
        KafkaMessage kafkaMessage = new KafkaMessage();
        kafkaMessage.setApplication_id(1L);
        kafkaMessage.setCompany_id(1111);
        TransactionRequestContext reqContext = refundConsumerService.createTxnRequestContext(kafkaMessage);
        // 构造预期请求体
        ChargeRequest expectedChargeRequest = refundConsumerService.buildChargeRequest(reqContext);

        // 修正后的打桩逻辑,假设第一个参数是字符串类型URI
        Mockito.when(restTemplate.postForEntity(
                anyString(),
                eq(expectedChargeRequest),
                eq(ChargeResponse.class)
        )).thenReturn(new ResponseEntity<>(chargeResponse, HttpStatus.OK));

        // 不需要精确匹配请求体可以用这个写法,适配性更高
        // Mockito.when(restTemplate.postForEntity(anyString(), any(), eq(ChargeResponse.class)))
        //        .thenReturn(new ResponseEntity<>(chargeResponse, HttpStatus.OK));

        // 执行测试方法
        refundConsumerService.refund(kafkaMessage);
        // 结果校验
        assertEquals(chargeResponse.getInstanceKey(), "testInstanceKey");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:36:03