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

如何Mock Spring WebClient及其builder解决Mock不生效问题

解决方案

你遇到的Mock不生效核心原因是业务代码直接调用WebClient.builder()静态方法生成实例,没有关联到你预先定义的Mock对象,可通过以下两种方案解决:

方案1:依赖注入重构(推荐)

该方案不需要修改现有测试逻辑,仅需调整业务代码的WebClient实例化方式,是Spring项目的最佳实践:

  1. 新增配置类将WebClient注入Spring容器:
@Configuration
public class CustomWebClientConfig {
    @Bean
    public WebClient customWebClient() {
        return WebClient.builder()
                .exchangeStrategies(ExchangeStrategies.builder()
                .codecs(configurer -> configurer
                        .defaultCodecs()
                        .maxInMemorySize(16 * 1024 * 1024))
                .build())
                .clientConnector(new ReactorClientHttpConnector(HttpClient.newConnection().compress(true)))
                .build();
    }
}
  1. 业务代码中删除硬编码的WebClient builder逻辑,改用注入方式获取实例:
@Service
public class YourService {
    // 直接注入容器中的WebClient实例
    private final WebClient customWebClient;

    public YourService(WebClient customWebClient) {
        this.customWebClient = customWebClient;
    }

    // 原有调用逻辑直接使用注入的customWebClient即可
    public JsonNode yourMethod() {
        return customWebClient
            .get()
            .uri(URLDecoder.decode(someEndpoint.replace("\"", ""), CLIENT_ENCODING))
            .header(AUTHORIZATION, BEARER + accessToken)
            .accept(MediaType.APPLICATION_JSON)
            .retrieve().bodyToMono(JsonNode.class).block();
    }
}
  1. 测试时直接用@MockBean替换容器中的WebClient实例即可,不需要处理builder逻辑:
@SpringBootTest
public class YourServiceTest {
    @MockBean
    private WebClient mockWebClient;
    @Autowired
    private YourService yourService;

    @Test
    public void test() {
        // 直接按普通Mock逻辑处理mockWebClient的调用即可
        WebClient.RequestHeadersUriSpec mockUriSpec = Mockito.mock(WebClient.RequestHeadersUriSpec.class);
        when(mockWebClient.get()).thenReturn(mockUriSpec);
        // 后续uri、header、retrieve等调用的Mock逻辑和你之前写的保持一致
    }
}

方案2:静态方法Mock(兼容未重构场景)

如果不能修改现有业务代码,可使用Mockito 3.4+的静态Mock能力,直接MockWebClient.builder()方法:

  1. 先引入mockito-inline依赖(默认的mockito-core不支持静态Mock)
  2. 测试用例写法如下:
@Test
public void test() {
    // 声明WebClient静态类的Mock作用域
    try (MockedStatic<WebClient> mockedWebClientStatic = Mockito.mockStatic(WebClient.class)) {
        // 初始化Mock的Builder和WebClient实例
        WebClient.Builder mockBuilder = Mockito.mock(WebClient.Builder.class);
        WebClient mockWebClient = Mockito.mock(WebClient.class);

        // 静态方法打桩:调用WebClient.builder()返回我们的Mock Builder
        mockedWebClientStatic.when(WebClient::builder).thenReturn(mockBuilder);
        // Builder链式调用的所有方法都要打桩返回自身,避免中间返回空指针
        when(mockBuilder.exchangeStrategies(any(ExchangeStrategies.class))).thenReturn(mockBuilder);
        when(mockBuilder.clientConnector(any(ClientHttpConnector.class))).thenReturn(mockBuilder);
        when(mockBuilder.build()).thenReturn(mockWebClient);

        // 后续按原有逻辑Mock mockWebClient的调用即可
        WebClient.RequestHeadersUriSpec mockUriSpec = Mockito.mock(WebClient.RequestHeadersUriSpec.class);
        when(mockWebClient.get()).thenReturn(mockUriSpec);
        // 剩余uri、header、retrieve等调用的Mock逻辑保持不变
    }
}

注意:静态Mock的作用域仅限try-with-resources代码块内,不会影响其他测试用例,所有Builder链式调用的方法都必须打桩,否则会抛出空指针异常


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 03:27:04