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

Introduce an alternative to WebTestClient based on RestClient #31275

Open
EvaristeGalois11 opened this issue Sep 19, 2023 · 10 comments
Open

Introduce an alternative to WebTestClient based on RestClient #31275

EvaristeGalois11 opened this issue Sep 19, 2023 · 10 comments
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement

Comments

@EvaristeGalois11
Copy link

Hi, I searched the other issues discussing the introduction of RestClient but i couldn't find anything regarding this topic. I apologize if it's been already discussed somewhere.

Currently the only way to call a controller in a RANDOM_PORT environment is through TestRestTemplate (which is a spring boot addition) or with a RestClient instance built for the task. Both of this approaches aren't very nice, given that one must extract from the response object all the parts and then manually asserting on them. WebClientTest on the other hand has a really nice api with the assertions baked in, but it needs all the reactive stuff to be brought in.

A third party alternative is REST Assured which works quite well and has a very nice api, but it would be better i think to not have to rely on some external libraries for this type of thing.

Could it be possible to add a very similar api to WebTestClient (RestTestClient?) but without the reactive side of it?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Sep 19, 2023
@bclozel
Copy link
Member

bclozel commented Sep 19, 2023

RestClient is using the same underlying infrastructure as RestTemplate. You can use the same testing infrastructure as a result.

Would spring-projects/spring-boot#37033 solve the problem for you?

@bclozel bclozel added the status: waiting-for-feedback We need additional information before we can continue label Sep 19, 2023
@EvaristeGalois11
Copy link
Author

EvaristeGalois11 commented Sep 19, 2023

But correct me if I'm wrong @bclozel, the problem is that the testing infrastructure for RestTemplate is very lacking because it was put in maintenance mode a long time ago.

This is how I'd call a controller with TestRestTemplate:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SomeTestIT {
  @Autowired private TestRestTemplate rest;

  @Test
  void someTest() {
    var response = rest.getForEntity("/something", Something.class);
    assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    assertThat(response.getBody()).usingRecursiveComparison().isEqualTo(expectedObject);
  }
}

There is basically nothing that helps testing the http call itself, all the assertions are manual.

This is instead how it's done with WebTestClient:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SomeTestIT {
  @Autowired private WebTestClient webTestClient;

  @Test
  void someTest() {
    webTestClient
        .get()
        .uri("/something")
        .exchange()
        .expectStatus()
        .isOk()
        .expectBody(Something.class)
        .isEqualTo(expectedObject);
  }
}

It's just a much more polished and pleasant api to work with. Also it could easily be integrated with spring rest docs to generate some nice documentation, which couldn't be done with TestRestTemplate because it isn't supported 😢 .

Regarding spring-projects/spring-boot#37033 I don't think it is enough because they are discussing about a RestClient.Builder being provided by spring boot, which at most can permit to construct a bare bone RestClient which has the same problems of TestRestTemplate.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Sep 19, 2023
@bclozel bclozel added in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on status: feedback-provided Feedback has been provided labels Sep 19, 2023
@bclozel bclozel added this to the 6.x Backlog milestone Sep 19, 2023
@sbrannen sbrannen changed the title Introduce an alternative to WebTestClient based on RestClient Introduce an alternative to WebTestClient based on RestClient Sep 20, 2023
@rstoyanchev
Copy link
Contributor

rstoyanchev commented Dec 4, 2023

@EvaristeGalois11 you probably are aware, but just in case, you can use WebTestClient against MockMvc as the server. There are examples of that throughout the reference docs. Also, as a test client, WebTestClient has a synchronous API, and you don't need to be exposed to anything reactive unless you want to (e.g. if streaming events).

@bclozel bclozel changed the title Introduce an alternative to WebTestClient based on RestClient Introduce an alternative to WebTestClient based on RestClient Feb 14, 2024
@ciscoo
Copy link

ciscoo commented Apr 1, 2024

you don't need to be exposed to anything reactive unless you want to (e.g. if streaming events).

You would still need spring-webflux on the classpath which is kind of (not really but still) exposing reactive bits. Without it the default (DefaultWebTestClientBuilder) throws an error.

@wind57
Copy link
Contributor

wind57 commented Apr 3, 2024

@ciscoo

<scope>test</scope> ?

@MrBuddyCasino
Copy link

I was just looking for a test equivalent of RestClient and stumbled over this issue, because I wanted to avoid adding the webflux dependency (reactive API is the plague and thankfully killed by virtual threads).

Using WebTestClient in the meantime is ok I guess, since the dependency scope can be limited to test, but it feels unnecessary. Would appreciate it if this would be put on the roadmap.

@harutyunyan-vahe
Copy link

IMHO when you introduce new api (RestClient) it should be "complete". Saying that use RestClient in application and WebTestClient in the test is little bit confusing and not consistent - especially for new users who just coming to Spring.

@donalmurtagh
Copy link

donalmurtagh commented Sep 12, 2024

I've created a sample application to demonstrate a problem with using RestClient for testing. If you checkout the run-tests-in-mock-env branch of this app, it contains these tests:

  1. RandomPortTests uses RestClient with a real server which passes
  2. MockRestClientTests uses RestClient with a mock server which fails
  3. MockWebClientTests uses WebTestClient with a mock server which passes

If you start the server before running (2) the test passes, so it seems the reason for the failure is the server is not running.

However, it's not necessary to start the server before running (3). If it's possible for the test in (3) to pass without starting the server, then it ought to be possible with (2), because the only obvious difference between these tests is the client library.

@spencergibb
Copy link
Member

@jhoeller jhoeller modified the milestones: 6.x Backlog, General Backlog Oct 1, 2024
@rworsnop
Copy link

rworsnop commented Jan 6, 2025

I'm working on this here.
Quite a bit of fleshing out to do and tests to add, but should have a PR fairly soon.

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: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests