WebClient Testing - Testing External API Calls with MockWebServer
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.