Home Tutorial: Testing HTTP Requests with WebTestClient
Post
Cancel

Tutorial: Testing HTTP Requests with WebTestClient

Spring WebClient is a non-blocking, reactive HTTP client library introduced in Spring WebFlux, which is part of the Spring Framework. It provides a convenient way to make HTTP requests and consume RESTful APIs in a reactive and asynchronous manner. WebTestClient, on the other hand, is a testing utility provided by Spring Framework to test WebClient-based applications.

In this tutorial, we’ll cover the following topics:

  1. Setting up a Spring Boot project with WebClient
  2. Making GET, POST, PUT, and DELETE requests with WebClient
  3. Handling response data and errors with WebClient
  4. Testing WebClient-based applications using WebTestClient

Let’s get started!

1. Setting up a Spring Boot project with WebClient

To begin, make sure you have a Java Development Kit (JDK) installed on your machine. You’ll also need an IDE such as IntelliJ IDEA or Eclipse.

  1. Create a new Spring Boot project using the Spring Initializr (https://start.spring.io) or your preferred IDE.
  2. Include the following dependencies in your project’s pom.xml (for Maven) or build.gradle (for Gradle):
1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
  1. Set up a simple Spring Boot application class with an @SpringBootApplication annotation:
1
2
3
4
5
6
7
8
9
10
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebClientDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebClientDemoApplication.class, args);
    }
}
  1. Create a service or controller class where you’ll use WebClient to make HTTP requests. For demonstration purposes, let’s create a UserService class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

@Service
public class UserService {

    private final WebClient webClient;

    public UserService() {
        this.webClient = WebClient.create();
    }

    // Implement your methods to make HTTP requests using WebClient
    // ...
}

With the initial setup complete, we can move on to making HTTP requests with WebClient.

2. Making GET, POST, PUT, and DELETE requests with WebClient

WebClient provides methods for various HTTP request types. Let’s see how to use them.

GET Request

To make a GET request with WebClient, use the get() method and provide the request URL. You can then retrieve the response using the retrieve() method.

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;

// ...

ResponseSpec response = webClient.get()
    .uri("https://api.example.com/users")
    .retrieve();

String responseBody = response.bodyToMono(String.class).block();
System.out.println(responseBody);

POST Request

To make a POST request, use the post() method and provide the request URL. You can then send the request body using the body() method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;

// ...

ResponseSpec response = webClient.post()
    .uri("https://api.example.com/users")
    .contentType(MediaType.APPLICATION_JSON)
    .bodyValue(userJson)
    .retrieve();

String responseBody = response.bodyToMono(String.class).block();
System.out.println(responseBody);

PUT Request

To make a PUT request, use the put() method and provide the request URL. You can send the request body using the body() method, similar to the POST request.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;

// ...

ResponseSpec response = webClient.put()
    .uri("https://api.example.com/users/{id}", userId)
    .contentType(MediaType.APPLICATION_JSON)
    .bodyValue(updatedUserJson)
    .retrieve();

String responseBody = response.bodyToMono(String.class).block();
System.out.println(responseBody);

DELETE Request

To make a DELETE request, use the delete() method and provide the request URL.

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;

// ...

ResponseSpec response = webClient.delete()
    .uri("https://api.example.com/users/{id}", userId)
    .retrieve();

String responseBody = response.bodyToMono(String.class).block();
System.out.println(responseBody);

3. Handling response data and errors with WebClient

WebClient provides various methods to handle response data and errors. Here are a few examples:

Handling JSON response

If the response from the server is in JSON format, you can deserialize it into a Java object using the bodyToMono() method.

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;

// ...

ResponseSpec response = webClient.get()
    .uri("https://api.example.com/users/{id}", userId)
    .retrieve();

User user = response.bodyToMono(User.class).block();
System.out.println(user.getName());

Handling error responses

You can use the onStatus() method to handle specific HTTP status codes and errors returned by the server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;
import org.springframework.web.reactive.function.client.WebClientException;

// ...

ResponseSpec response = webClient.get()
    .uri("https://api.example.com/users/{id}", userId)
    .retrieve();

response.onStatus(HttpStatus.NOT_FOUND, clientResponse -> {
    throw new WebClientException("User not found");
});

User user = response.bodyToMono(User.class).block();
System.out.println(user.getName());

4. Testing WebClient-based applications using WebTestClient

Spring Framework provides WebTestClient to test WebClient-based applications. You can use it to mock HTTP responses and verify request parameters.

To use WebTestClient, follow these steps:

  1. Add the following dependency to your project’s test scope in the pom.xml (for Maven) or build.gradle (for Gradle):
1
2
3
4
5
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. Create a test class and annotate it with @RunWith(SpringRunner.class) (for JUnit 4) or @ExtendWith(SpringExtension.class) (for JUnit 5). Add the @SpringBootTest annotation to load the Spring context.
1
2
3
4
5
6
7
8
9
10
11
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@RunWith(SpringRunner.class)
@SpringBootTest
public class WebClientTests {

    // ...
}
  1. Create a WebTestClient instance and use it to perform HTTP requests and verify responses.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;

@SpringBootTest
public class WebClientTests {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    public void testGetUser() {
        webTestClient.get()
                .uri("/users/{id}", "123")
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isOk()
                .expectBody(User.class)
                .value(user -> assertEquals("John Doe", user.getName()));
    }

    // ...
}

In the example above, we use WebTestClient to make a GET request to /users/123 and expect an HTTP status of 200 (OK). We also expect the response body to be deserialized into a User object and verify its name.

That’s it! You’ve learned how to use Spring WebClient and WebTestClient to make HTTP requests, handle responses, and test WebClient-based applications.

Feel free to explore more features provided by WebClient and WebTestClient to suit your application’s needs.

This post is licensed under CC BY 4.0 by the author.