For TestRestClient context path is autoconfigured as base by default, it is a bit confusing to have both clients autoconfigured with the different base paths. Also I don't see any possibility to configure base path for WebTestClient since it is hardcoded on creation: return builder.baseUrl(baseUrl).build();

Now I understand why servlet.contextPath is not used since it is not reactive based, but if it is possible to use for non-reactive it should be at least configurable.

I'd like to have possibility to customize base path for WebTestClient.

Comment From: sbrannen

For TestRestClient context path is autoconfigured as base by default

Are you referring to the TestRestTemplate in Spring Boot Test?

Comment From: 20fps

For TestRestClient context path is autoconfigured as base by default

Are you referring to the TestRestTemplate in Spring Boot Test?

Yes

Comment From: rstoyanchev

@20fps this can be done currently as follows:

MockMvcBuilders.webAppContextSetup(this.wac)
        .defaultRequest(get("/").contextPath("/myapp"))
        .build();

This should work well as long as you want the same context path for all tests in the fixture but it would be less convenient for a one-off test case. I suppose we could expose convenience methods directly on MockMvcServerSpec for this.

Comment From: rstoyanchev

On second thought, exposing a convenience method in MockMvcServerSpec is just that, a convenience over doing the same via defaultRequest(..). In other words there is no way to set this per request and it must be set per WebTestClient instance instead. This makes sense since with just MockMvc you are on the server side each time you set up an HttpServletRequest and that gives you an opportunity to set the contextPath, while with WebTestClient you are on the client side and there is no way to set the contextPath which is a server side concept.

So I'm closing this without any further changes for now in favor of the sample shown above which is also consistent with how it's set at the MockMvc level when using just MockMvc.

Comment From: 20fps

@rstoyanchev what do you mean by MockMvc? I'm using @SpringBootTest with random port and WebTestClient as a client for my integration tests. MockMvc should not be used for integration tests.

Comment From: rstoyanchev

I misunderstood the scenario. Disregard my previous comments.

I don't see any possibility to configure base path for WebTestClient since it is hardcoded on creation: return builder.baseUrl(baseUrl).build();

Can you clarify where this is hard-coded?

Comment From: 20fps

Can you clarify where this is hard-coded?

Sure org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizer.WebTestClientFactory#getObject Here's the code:

@Override
public WebTestClient getObject() throws Exception {
  if (this.object == null) {
    this.object = createWebTestClient();
  }
  return this.object;
}

private WebTestClient createWebTestClient() {
  boolean sslEnabled = isSslEnabled(this.applicationContext);
  String port = this.applicationContext.getEnvironment().getProperty("local.server.port", "8080");
  String baseUrl = (sslEnabled ? "https" : "http") + "://localhost:" + port;
  WebTestClient.Builder builder = WebTestClient.bindToServer();
  customizeWebTestClientBuilder(builder, this.applicationContext);
  customizeWebTestClientCodecs(builder, this.applicationContext);
  return builder.baseUrl(baseUrl).build();
}

Comment From: bclozel

@20fps I have a hard time following this. It's not clear if you'd like another extension point in WebTestClient itself to further customize or reset the base URL of the client, or if you disagree with Spring Boot's defaults in this case.

Also, I'm not sure I understand how TestRestTemplate and WebTestClient are behaving differently and where the behavior should be aligned.

Maybe you could provide two code snippets, one @Test method using TestRestTemplate and another using WebTestClient, and explain what is the difference about base URLs. I also fail to understand how the Servlet context path is playing a role here and how that applies to the WebFlux case.

Thanks!

Comment From: 20fps

@bclozel sure, here is an example:

@SpringBootTest(
    webEnvironment = WebEnvironment.RANDOM_PORT,
    classes = SampleApplicationTest.SampleApplication.class)
@TestPropertySource(properties = "server.servlet.context-path=/test")
class SampleApplicationTest {

  @Autowired
  private TestRestTemplate testRestTemplate;
  @Autowired
  private WebTestClient webTestClient;

  @Test
  void shouldReturnResourcesUsingTestRestTemplate() {
    var actual = testRestTemplate.getForEntity("/resources", String.class);

    assertThat(actual.getStatusCode()).isEqualTo(OK);
    assertThat(actual.getBody()).isEqualTo("test-resource");
  }

  // will fail with 404 cos context path is not configured
  @Test
  void shouldReturnResourcesUsingWebTestClient() {
    webTestClient.get().uri("/resources").exchange()
        .expectStatus().isOk()
        .expectBody(String.class).isEqualTo("test-resource");
  }

  @SpringBootApplication
  static class SampleApplication {

    static void main(String[] args) {
      SpringApplication.run(SampleApplication.class, args);
    }

    @RestController
    static class Controller {
      @GetMapping("/resources")
      String resources() {
        return "test-resource";
      }
    }
  }
}

I'd like to have possibility to customize baseUrl for WebTestClient to include contextPath just like for TestRestTemplate.

From the example above, let's assume random port will be 8080:

  • for TestRestTemplate base path is configured as http://localhost:8080/test and passing url as /resources will be resolved as request to http://localhost:8080/test/resources
  • for WebTestClient base path is configured as http://localhost:8080 and the same /resources will be resolved as request to http://localhost:8080/resources and 404 response

I'd like to have possibility to customize base path as generated_host + custom_path without having to create WebTestClient instance by my own.