Skip to content

12.3.3 Testing with a live server

The tests you’ve written so far have relied on a mock implementation of the Spring WebFlux framework so that a real server wouldn’t be necessary. But you may need to test a WebFlux controller in the context of a server like Netty or Tomcat and maybe with a repository or other dependencies. That is to say, you may want to write an integration test.

To write a WebTestClient integration test, you start by annotating the test class with @RunWith and @SpringBootTest like any other Spring Boot integration test, as shown here:

java
package tacos;

import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class TacoControllerWebTest {

  @Autowired
  private WebTestClient testClient;

}

By setting the webEnvironment attribute to WebEnvironment.RANDOM_PORT, you’re asking Spring to start a running server listening on a randomly chosen port.

You’ll notice that you’ve also autowired a WebTestClient into the test class. This not only means that you’ll no longer have to create one in your test methods but also that you won’t need to specify a full URL when making requests. That’s because the WebTestClient will be rigged to know which port the test server is running on. Now you can rewrite shouldReturnRecentTacos() as an integration test that uses the autowired WebTestClient as follows:

java
@Test
public void shouldReturnRecentTacos() throws IOException {
  testClient.get().uri("/api/tacos?recent")
    .accept(MediaType.APPLICATION_JSON).exchange()
    .expectStatus().isOk()
    .expectBody()
      .jsonPath("$").isArray()
      .jsonPath("$.length()").isEqualTo(3)
      .jsonPath("$[?(@.name == 'Carnivore')]").exists()
      .jsonPath("$[?(@.name == 'Bovine Bounty')]").exists()
      .jsonPath("$[?(@.name == 'Veg-Out')]").exists();
}

You’ve no doubt noticed that this new version of shouldReturnRecentTacos() has much less code. You no longer need to create a WebTestClient because you’ll be making use of the autowired instance. And you don’t have to mock TacoRepository because Spring will create an instance of TacoController and inject it with a real TacoRepository. In this new version of the test method, you use JSONPath expressions to verify values served from the database.

WebTestClient is useful when, in the course of a test, you need to consume the API exposed by a WebFlux controller. But what about when your application itself consumes some other API? Let’s turn our attention to the client side of Spring’s reactive web story and see how WebClient provides a REST client that deals in reactive types such as Mono and Flux.

Released under the MIT License.