升级至Spring Boot 3.4.0后Spring Cloud Gateway测试失败
Spring Boot 3.4.0升级后Gateway过滤器测试失败问题解答
1. 这是已知的破坏性变更吗?
这属于规范对齐的破坏性变更,并非意外bug。Spring Framework 6.2修正了MockServerWebExchange的行为,使其严格遵循ServerWebExchange的设计原则:原始exchange实例是不可变的,通过mutate()创建的是全新实例,而非修改原对象。
在6.1.x及之前版本中,Mock实现意外允许了对原实例的修改,这其实不符合官方规范,6.2版本的修正让Mock行为和生产环境的真实ServerWebExchange保持一致,该调整可能未在发布说明中单独强调。
2. 当前在Gateway过滤器测试中验证请求头及服务交互的正确方式是什么?
验证请求头修改
过滤器中传递给GatewayFilterChain的是新的exchange实例,原实例不会被修改,因此测试时需要捕获这个新实例,而非直接断言原exchange。
修改后的测试代码示例:
@ExtendWith(MockitoExtension.class) class TestGatewayFilterTest { @InjectMocks private TestGatewayFilter testGatewayFilter; @Test void shouldRunFilter() { MockServerHttpRequest mockRequest = MockServerHttpRequest .get("/testfilter") .build(); MockServerWebExchange exchange = MockServerWebExchange.from(mockRequest); // 自定义FilterChain,捕获传递的新exchange AtomicReference<ServerWebExchange> capturedExchange = new AtomicReference<>(); Mono<Void> result = testGatewayFilter.filter(exchange, e -> { capturedExchange.set(e); return Mono.empty(); }); StepVerifier.create(result) .verifyComplete(); // 断言捕获到的新exchange中的请求头 assertEquals("test", capturedExchange.get().getRequest().getHeaders().getFirst("test-header")); } }
验证服务交互
如果需要验证过滤器是否触发下游服务调用,可通过两种方式实现:
- 自定义FilterChain捕获请求细节:在自定义链中检查exchange的目标地址、请求方法等信息,确认是否符合预期。
- 结合MockWebServer模拟下游服务:通过MockWebServer模拟下游服务,验证过滤器转发的请求是否正确到达,且携带修改后的请求头。
示例(MockWebServer方式):
首先添加依赖:
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>mockwebserver</artifactId> <scope>test</scope> </dependency>
测试代码:
@Test void shouldForwardToDownstreamService() throws IOException { MockWebServer mockWebServer = new MockWebServer(); mockWebServer.start(); // 配置Gateway路由指向Mock服务 RouteLocator routeLocator = RouteLocatorBuilder.routeLocatorBuilder() .routes(r -> r.path("/testfilter") .uri(mockWebServer.url("/").toString()) .filter(testGatewayFilter)) .build(); WebTestClient webTestClient = WebTestClient.bindToRouterFunction(routeLocator).build(); // 发送测试请求 webTestClient.get().uri("/testfilter") .exchange() .expectStatus().isOk(); // 验证Mock服务收到的请求头 RecordedRequest recordedRequest = mockWebServer.takeRequest(); assertEquals("test", recordedRequest.getHeader("test-header")); mockWebServer.shutdown(); }
3. 若这是意外行为,应向何处反馈?
如果确认问题是不符合预期的bug(而非规范对齐的变更),可通过以下官方渠道反馈:
- 若问题和Spring Framework的
MockServerWebExchange相关,提交到Spring Framework的官方GitHub仓库Issue板块 - 若问题和Spring Cloud Gateway组件逻辑相关,提交到Spring Cloud Gateway的官方GitHub仓库Issue板块
内容的提问来源于stack exchange,提问作者John Bubbles
相关产品推荐
相关产品推荐

