Skip to content

Conversation

@rjuare8
Copy link
Contributor

@rjuare8 rjuare8 commented Nov 30, 2025

Deflake keepOriginalEncodingOfQueryParameter by relaxing URI ordering assertion

While running the Spring Cloud Gateway MVC tests (including with tools like NonDex), I observed non-deterministic failures in ProxyExchangeHandlerFunctionTest.keepOriginalEncodingOfQueryParameter().

The original test asserted that the entire URI, including the precise ordering of query parameters, exactly matched a hard-coded value:

assertThat(uri).hasToString(
    "http://localhost:8080/%C3%A9?foo=value1%20value2&bar=value3%3D&qux=value4%2B"
)
.hasPath("/é")
.hasParameter("foo", "value1 value2")
.hasParameter("bar", "value3=")
.hasParameter("qux", "value4+");

However, the order of query parameters is not guaranteed. When the iteration order of parameters changes (for example, under NonDex’s randomized iteration), the resulting URI may still contain exactly the same parameters and encodings
but in a different order. In that case, the hasToString assertion fails even though the behavior of ProxyExchangeHandlerFunction is correct.

This is a classic implementation-dependent (ID) flaky test pattern: the test is asserting on concrete implementation details (a specific parameter ordering) rather than the actual contract (preserving the encoded path and parameter values).

This PR updates the test to verify that the URI contains the expected path and query fragments independently of their order, while still asserting on the decoded path and parameter values:

URI uri = proxyExchange.getRequest().getUri();


assertThat(uri.toString()).contains(
    "http://localhost:8080/%C3%A9?",
    "foo=value1%20value2",
    "bar=value3%3D",
    "qux=value4%2B"
);

assertThat(uri).hasPath("/é")
    .hasParameter("foo", "value1 value2")
    .hasParameter("bar", "value3=")
    .hasParameter("qux", "value4+");

Summary of changes

spring-cloud-gateway-server-webmvc/src/test/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunctionTest.java:

Before:

URI uri = proxyExchange.getRequest().getUri();

assertThat(uri).hasToString(
    "http://localhost:8080/%C3%A9?foo=value1%20value2&bar=value3%3D&qux=value4%2B"
)
.hasPath("/é")
.hasParameter("foo", "value1 value2")
.hasParameter("bar", "value3=")
.hasParameter("qux", "value4+");

After:

URI uri = proxyExchange.getRequest().getUri();

assertThat(uri.toString()).contains(
    "http://localhost:8080/%C3%A9?",
    "foo=value1%20value2",
    "bar=value3%3D",
    "qux=value4%2B"
);

assertThat(uri).hasPath("/é")
    .hasParameter("foo", "value1 value2")
    .hasParameter("bar", "value3=")
    .hasParameter("qux", "value4+");

Copy link
Contributor

@raccoonback raccoonback left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants