WebClient Testing - Testing External API Calls with MockWebServer

What MockWebServer is and how to use it

Overview

Most modern services are expected to call REST APIs. Spring provides several options for building REST clients and recommends WebClient.

This page explains how to unit test a service that calls an API by using WebClient.

What Is MockWebServer?

MockWebServer from Square is a small, simple web server that receives HTTP requests and returns responses.

When testing methods that call HTTP through clients such as WebClient or RestTemplate, you can point the client to MockWebServer and write tests more easily. The Spring team also recommends using MockWebServer for this kind of test.

Creating a Simple WebClient Project

Before using MockWebServer, create a simple project that uses WebClient as the test target. The sample project can be generated from Spring Initializr with Java 11, Gradle, Spring Boot 2.7.6, and the webflux dependency.

Create a DTO object to receive data, then create service code that uses WebClient to call /users/{id} and returns Mono<User>.

Applying MockWebServer

Adding the Dependency

Add the MockWebServer test dependency.

dependencies {
    testImplementation 'com.squareup.okhttp3:mockwebserver'
}

Adding MockWebServer to Test Code

In test code, create a MockWebServer object in @BeforeAll, start it, and shut it down in @AfterAll.

Passing WebClient to the Service

Create a WebClient with a base URL that uses the MockWebServer port and pass it to the service.

@BeforeEach
void initialize() {
    final String baseUrl = String.format("http://localhost:%s", mockWebServer.getPort());
    final WebClient webClient = WebClient.create(baseUrl);
    userService = new UserService(webClient);
}

With this setup, the test calls MockWebServer instead of a real external URL.

Creating an Arbitrary Response

Create a MockResponse, set the body and headers, and put it into enqueue. MockWebServer returns responses in the order they were enqueued.

Checking the Request

Besides checking the response value, you can also inspect the request with takeRequest().

final RecordedRequest recordedRequest = mockWebServer.takeRequest();
assertAll(
        () -> assertEquals("GET", recordedRequest.getMethod()),
        () -> assertEquals("/users/3", recordedRequest.getPath())
);

References


The example code above is available on GitHub.