SpringBoot 3响应式应用WebTestClient返回404而非200求助
SpringBoot 3响应式WebTestClient测试返回404问题排查
我在测试SpringBoot(3)响应式应用的REST层时,使用Spring的WebTestClient遇到了问题:运行应用时用Postman能正常访问端点并返回200,但测试代码却持续返回404。
测试代码如下:
@ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = ReferenceDataApplication.class) public class RefDataResourceTest { @Autowired private WebTestClient webTestClient; @BeforeEach void setup() { webTestClient = WebTestClient.bindToController(new RefDataResource()).build(); } @Test public void shouldGetReferenceDataByTypeCode() { webTestClient .get() .uri("/api/projects/refData/findByCode") .exchange() .expectStatus().isOk(); } }
资源类实现了OpenApi生成的委托类,Spring中定义了/api/projects/作为基础路径:
@Component public class RefDataResource implements RefDataApiDelegate { @Override public Mono<ResponseEntity<Flux<RefDataElementDTO>>> findDataByCode(String code, ServerWebExchange exchange) { return Mono.just(ResponseEntity.ok().build()); } }
问题原因及修复方法
核心错误:手动构建WebTestClient覆盖了上下文配置
你在@BeforeEach中用bindToController重新创建WebTestClient实例,这种方式属于孤立控制器测试,只会加载单个控制器的逻辑,不会读取Spring上下文的全局配置——比如你定义的/api/projects/基础路径、OpenApi生成的路由映射规则等。而Postman访问的是完整启动的应用,自然能匹配到正确路径。修复步骤:移除手动构建逻辑
保留@Autowired注入的WebTestClient即可,它是基于@SpringBootTest启动的完整上下文生成的,会自动包含所有路径前缀和路由配置。修改后的测试类:
@ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = ReferenceDataApplication.class) public class RefDataResourceTest { @Autowired private WebTestClient webTestClient; // 移除原setup方法 @Test public void shouldGetReferenceDataByTypeCode() { webTestClient .get() .uri("/api/projects/refData/findByCode") .exchange() .expectStatus().isOk(); } }
- 额外注意:参数缺失问题
你的findDataByCode方法需要接收String code参数,但当前测试代码没有传递该参数。如果OpenApi生成的路由要求该参数(作为请求参数或路径变量),即使修复了WebTestClient的问题,仍可能返回4xx错误。需要根据实际路由规则补充参数,例如如果是请求参数:
webTestClient .get() .uri(uriBuilder -> uriBuilder .path("/api/projects/refData/findByCode") .queryParam("code", "test-demo-code") .build()) .exchange() .expectStatus().isOk();
内容的提问来源于stack exchange,提问作者Diferdin
相关产品推荐
相关产品推荐

