Fix WebClientIntegrationTest#applyAttributesToNativeRequest flaky test

For Reactor Netty and Reactor Netty 2 (with Netty 5), the attributes are
stored as an `Attribute` on the netty channel. Reactor Netty replaces
the channel with a static placeholder one once the request has been
processed and as such, capturing the native request in the test will
lead to asserting an attribute-less channel.

This change switches to capturing the `Attribute` itself, which is a
value-holder that can be asserted later on.

Closes gh-33909
This commit is contained in:
Simon Baslé 2024-11-18 16:30:16 +01:00
parent f5c3f3522e
commit d597d2e159
1 changed files with 18 additions and 8 deletions

View File

@ -83,7 +83,6 @@ import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;
import org.springframework.web.testfixture.xml.Pojo; import org.springframework.web.testfixture.xml.Pojo;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.junit.jupiter.params.provider.Arguments.argumentSet; import static org.junit.jupiter.params.provider.Arguments.argumentSet;
/** /**
@ -108,6 +107,7 @@ class WebClientIntegrationTests {
static Stream<Arguments> arguments() { static Stream<Arguments> arguments() {
return Stream.of( return Stream.of(
argumentSet("Reactor Netty", new ReactorClientHttpConnector()), argumentSet("Reactor Netty", new ReactorClientHttpConnector()),
argumentSet("Reactor Netty 2", new ReactorNetty2ClientHttpConnector()),
argumentSet("JDK", new JdkClientHttpConnector()), argumentSet("JDK", new JdkClientHttpConnector()),
argumentSet("Jetty", new JettyClientHttpConnector()), argumentSet("Jetty", new JettyClientHttpConnector()),
argumentSet("HttpComponents", new HttpComponentsClientHttpConnector()) argumentSet("HttpComponents", new HttpComponentsClientHttpConnector())
@ -193,8 +193,6 @@ class WebClientIntegrationTests {
@ParameterizedWebClientTest @ParameterizedWebClientTest
void applyAttributesToNativeRequest(ClientHttpConnector connector) { void applyAttributesToNativeRequest(ClientHttpConnector connector) {
assumeFalse(connector instanceof ReactorClientHttpConnector,
"Temporarily disabling flaky test for Reactor Netty");
startServer(connector); startServer(connector);
prepareResponse(response -> {}); prepareResponse(response -> {});
@ -202,20 +200,32 @@ class WebClientIntegrationTests {
Mono<Void> result = this.webClient.get() Mono<Void> result = this.webClient.get()
.uri("/pojo") .uri("/pojo")
.attribute("foo","bar") .attribute("foo","bar")
.httpRequest(clientHttpRequest -> nativeRequest.set(clientHttpRequest.getNativeRequest())) .httpRequest(clientHttpRequest -> {
if (clientHttpRequest instanceof ChannelOperations<?,?> nettyReq) {
nativeRequest.set(nettyReq.channel().attr(ReactorClientHttpConnector.ATTRIBUTES_KEY));
}
else if (clientHttpRequest instanceof reactor.netty5.channel.ChannelOperations<?,?> nettyReq) {
nativeRequest.set(nettyReq.channel().attr(ReactorNetty2ClientHttpConnector.ATTRIBUTES_KEY));
}
else {
nativeRequest.set(clientHttpRequest.getNativeRequest());
}
})
.retrieve() .retrieve()
.bodyToMono(Void.class); .bodyToMono(Void.class);
StepVerifier.create(result).expectComplete().verify(); StepVerifier.create(result).expectComplete().verify();
if (nativeRequest.get() instanceof ChannelOperations<?,?> nativeReq) { if (nativeRequest.get() instanceof Attribute<?>) {
Attribute<Map<String, Object>> attributes = nativeReq.channel().attr(ReactorClientHttpConnector.ATTRIBUTES_KEY); @SuppressWarnings("unchecked")
Attribute<Map<String, Object>> attributes = (Attribute<Map<String, Object>>) nativeRequest.get();
assertThat(attributes.get()).isNotNull(); assertThat(attributes.get()).isNotNull();
assertThat(attributes.get()).containsEntry("foo", "bar"); assertThat(attributes.get()).containsEntry("foo", "bar");
} }
else if (nativeRequest.get() instanceof reactor.netty5.channel.ChannelOperations<?,?> nativeReq) { else if (nativeRequest.get() instanceof io.netty5.util.Attribute<?>) {
@SuppressWarnings("unchecked")
io.netty5.util.Attribute<Map<String, Object>> attributes = io.netty5.util.Attribute<Map<String, Object>> attributes =
nativeReq.channel().attr(ReactorNetty2ClientHttpConnector.ATTRIBUTES_KEY); (io.netty5.util.Attribute<Map<String, Object>>) nativeRequest.get();
assertThat(attributes.get()).isNotNull(); assertThat(attributes.get()).isNotNull();
assertThat(attributes.get()).containsEntry("foo", "bar"); assertThat(attributes.get()).containsEntry("foo", "bar");
} }