After upgrading to Spring Boot 3.4.0 (Spring Web 6.2.0), my Gateway filter tests started failing. The tests previously verified that request headers were modified correctly, but now the modifications don't seem to be visible in the test assertions.
Here's a simplified example that used to pass but now fails:
@Component
class TestGatewayFilter implements GatewayFilter {
public TestGatewayFilter() {
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Builder builder = exchange.getRequest().mutate();
builder.header("test-header", "test");
return chain.filter(exchange.mutate().request(builder.build()).build());
}
}
@ExtendWith(MockitoExtension.class)
class TestGatewayFilterTest {
@InjectMocks
private TestGatewayFilter testGatewayFilter;
@Test
void shouldRunFilter() {
MockServerHttpRequest mockRequest = MockServerHttpRequest
.get("/testfilter")
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(mockRequest);
Mono<Void> result = testGatewayFilter.filter(exchange, e -> Mono.empty());
StepVerifier.create(result)
.verifyComplete();
assertEquals("test", exchange.getRequest().getHeaders().getFirst("test-header"));
}
}
Dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
</parent>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<version>3.7.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.13.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-dependencies</artifactId>
<version>4.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
The test passes with Spring Boot 3.3.x (which includes Spring Web 6.1.x) but fails with 3.4.0 (which includes Spring web 6.2.x). I've looked through the Spring Framework 6.2 release notes but couldn't find any mention of changes to ServerWebExchange or MockServerWebExchange behavior.
I'd like to test whether other services are interacted with in this unit test too. Questions:
The assertion is performed on the wrong exchange: the original one instead of the mutated one. I'm not sure why this worked previously, maybe a Spring Cloud Gateway behavior change?
In any case, the test should be written like this:
@Test
void shouldRunFilter() {
MockServerHttpRequest mockRequest = MockServerHttpRequest
.get("/testfilter")
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(mockRequest);
Mono<Void> result = testGatewayFilter.filter(exchange, e -> {
assertEquals("test", e.getRequest().getHeaders().getFirst("test-header"));
return Mono.empty();
});
StepVerifier.create(result).verifyComplete();
}