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 defaultAre 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 ashttp://localhost:8080/test
and passing url as/resources
will be resolved as request tohttp://localhost:8080/test/resources
- for
WebTestClient
base path is configured ashttp://localhost:8080
and the same/resources
will be resolved as request tohttp://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.