Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation for uri(URI) method in WebTestClient regarding base URI #28058

Closed
SimoneGiusso opened this issue Feb 16, 2022 · 4 comments
Assignees
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Milestone

Comments

@SimoneGiusso
Copy link

SimoneGiusso commented Feb 16, 2022

Affects: Spring Boot 2.6.3 and below


During one of my integration tests, to test one endpoint I encountered the following error:

org.springframework.web.reactive.function.client.WebClientRequestException: Connection refused

I'm using the webflux starter version 2.6.3, but the problem I'm describing is reproducible with lower version.

These are the annotations applied to my test:

@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("test")
@Sql("classpath:sql/my_sql.sql")
@Import(TestConfig.class)

and this is the code is raising the issue:

        URI uri = UriComponentsBuilder
                .fromUriString(MY_URL)
                .queryParam("year", 2005)
                .buildAndExpand()
                .toUri();

        client.get()
                .uri(uri)
                .exchange()
                .expectStatus()
                .is2xxSuccessful();

After analyzing the problem, I found out that the issue is caused by the use of @SpringBootTest(webEnvironment = RANDOM_PORT) without @AutoConfigureWebTestClient (this should be possible since @SpringBootTest registers a WebTestClient) and the use of the S uri(URI uri); implementation in the UriSpec interface inside the WebTestClient interface.

In other words by rewriting the test as:

        URI uri = UriComponentsBuilder
                .fromUriString(MY_URL)
                .queryParam("year", 2005)
                .buildAndExpand()
                .toUri();

        client.get()
                .uri(uri.toString) // Using another method to specify the URI
                .exchange()
                .expectStatus()
                .is2xxSuccessful();

The DefaultWebTestClient is injected with a uriBuilderFactory (DefaultUriBuilderFactory) where its field private final UriComponentsBuilder baseUri; is not null.

In the first case the URI returned is missing the base URI (http//host:port/ -- for example, /myUrl?year=2005), whilst in the second case the URI returned contains the base URI (http//host:port/myUrl?year=2005).

Another workaround is to put (a redundant) annotation:

@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("test")
@Sql(value = "classpath:sql/my_sql.sql")
@Import({TestConfig.class})
@AutoConfigureWebTestClient // the DefaultWebTestClient will be injected with different property values.

In this case the DefaultWebTestClient is injected with private final UriComponentsBuilder baseUri; equals to null, then the methods:

S uri(URI uri);

S uri(String uri, Object... uriVariables);

are consistent: both return the URI without the base URI, but in this case everything works.

@SimoneGiusso SimoneGiusso changed the title Connection refused during integration test with reactive WebTestClient + UriComponentsBuilder Connection refused during integration test with special combination of reactive WebTestClient + UriComponentsBuilder Feb 16, 2022
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 16, 2022
@sbrannen
Copy link
Member

I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference.

Specifically, please avoid the use of @-mentions for annotations. Instead, please ensure that annotations are formatted as literals or code snippets.

@sbrannen
Copy link
Member

As stated in the Javadoc for WebTestClient.UriSpec.uri(String, Object...):

Specify the URI for the request using a URI template and URI variables. If a UriBuilderFactory was configured for the client (e.g. with a base URI) it will be used to expand the URI template.

By passing uri.toString(), you end up invoking this method which treats the URI string as a URI template and applies the base URI.

As stated in the Javadoc for WebTestClient.UriSpec.uri(URI):

Specify the URI using an absolute, fully constructed URI.

The URI used in your first example is not absolute and fully constructed, and the base URI is not applied.

Thus, the behavior you are experiencing is expected and by design; however, I think the Javadoc for WebTestClient.UriSpec.uri(URI) should state the difference more explicitly, and I'll repurpose this issue to address that.

@sbrannen sbrannen added in: test Issues in the test module type: documentation A documentation task in: web Issues in web modules (web, webmvc, webflux, websocket) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Feb 16, 2022
@sbrannen sbrannen self-assigned this Feb 16, 2022
@sbrannen sbrannen added this to the 5.3.16 milestone Feb 16, 2022
@sbrannen sbrannen changed the title Connection refused during integration test with special combination of reactive WebTestClient + UriComponentsBuilder Improve documentation for uri(URI) method in WebTestClient regarding base URI Feb 16, 2022
@SimoneGiusso
Copy link
Author

SimoneGiusso commented Feb 16, 2022

The URI used in your first example is not absolute and fully constructed, and the base URI is not applied.

This example works by adding the @AutoConfigureWebTestClient. In this case the base URI is not applied but the test pass. This is not specified in the documentation neither. I think this is not expected and it's not coherent from a developer prospective:

  • Without @AutoConfigureWebTestClient and with @SpringBootTest(webEnvironment = RANDOM_PORT), the tests don't work without the base URI
  • With @AutoConfigureWebTestClient and @SpringBootTest(webEnvironment = RANDOM_PORT), the tests work without the base URI

@sbrannen
Copy link
Member

This example works by adding the @AutoConfigureWebTestClient. In this case the base URI is not applied but the test pass. This is not specified in the documentation neither. I think this is not expected and it's not coherent from a developer prospective:

If you feel that something can be documented better in Javadoc or in the reference docs for the core Spring Framework, please let us know in this issue tracker.

Regarding the behavior of WebTestClient in combination with @AutoConfigureWebTestClient and @SpringBootTest, please open an issue in the Spring Boot issue tracker.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

3 participants