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

如何在无HttpServletRequest上下文场景下测试Spring Boot WebClient调用

解决方案

第一步:修正现有WebClient配置缺陷

  • 给Servlet环境专用的servletWebClient增加Servlet环境条件注解,避免非Servlet环境下尝试实例化该Bean:
    给该Bean添加@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)注解即可,生产环境为Servlet Web应用,该Bean会正常加载,非Servlet测试环境则不会注册。
  • 修正调度专用schedulerWebClient的过滤器实现:当前代码中该实例依然使用了ServletOAuth2AuthorizedClientExchangeFilterFunction,这个过滤器本身强制依赖Servlet请求上下文,哪怕配置了独立的OAuth2AuthorizedClientManager也会触发空指针错误,需要替换为不依赖Servlet环境的通用OAuth2AuthorizedClientExchangeFilterFunction,修正后的代码如下:
    @Bean
    @Qualifier("forScheduler")
    WebClient schedulerWebClient(@Qualifier("authorizedClientManagerForScheduler") OAuth2AuthorizedClientManager authorizedClientManager) {
      // 替换为通用OAuth2过滤器,不依赖Servlet请求上下文
      var oauth = new OAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
      oauth.setDefaultClientRegistrationId("keycloak");
      return WebClient.builder()
          .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
          .apply(oauth.oauth2Configuration())
          .build();
    }
    

第二步:编写非Servlet环境集成测试

关闭Web环境的同时手动导入OAuth2客户端自动配置,保证OAuth2相关核心Bean正常加载,测试类示例如下:

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.reactive.function.client.WebClient;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@Import(OAuth2ClientAutoConfiguration.class)
public class SchedulerWebClientTest {

    @Autowired
    @Qualifier("forScheduler")
    private WebClient schedulerWebClient;

    @Test
    void testSchedulerWebClientNoServletRequestError() {
        // 此处替换为你的调度任务逻辑,或者直接调用WebClient发起测试请求
        String result = schedulerWebClient.get()
                .uri("替换为实际要调用的外部服务测试地址")
                .retrieve()
                .bodyToMono(String.class)
                .block();
        // 断言返回结果正常,不会抛出servletRequest cannot be null异常
        assertNotNull(result);
    }
}

复现原问题验证

如果需要验证原错误场景,只需将schedulerWebClient的过滤器换回ServletOAuth2AuthorizedClientExchangeFilterFunction,再执行上述测试,即可复现生产环境的servletRequest cannot be null错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 10:36:07