[Spring Boot] Unit Testing Functional Endpoints and Service with API calls using Spring WebFlux

Jay Kim
2 min readSep 29, 2021

This article shows a few ways of writing unit tests to test drive the controller and service layers of a Reactive application.

How to test Functional Endpoints

Functional endpoints can be mapped by defining a RouterFunction bean. Let us look at an example below which maps 4 endpoints. It can be observed that each endpoint is mapped with HandlerFunction (userHandler) in the example. Also, the order of the endpoints matters. For example, if /{id} endpoint is declared before /posts, whenever /posts is called, it parses “posts” as the id and it will trigger userHandler.getUser("posts") instead of userHandler.getPostsByUsers().

Functional Endpoints mapping

For each HandlerFunction, it takes in ServerRequest as a parameter and returns a Mono<ServerResponse>.

UserHandler implementation

The mapped endpoints can be tested with WebTestClient. When building a WebTestClient, it can bind to a specific RouterFunction.

Functional Endpoints Unit Tests

How to test Services which use WebClient

When implementing business logic, there will be times where an external API is required. WebClient is used to invoke the APIs. However, WebClient is part of the logic and it is important for the test code to have to control over the behavior and the return values of the external API invoked with WebClient.

Imagine the service implementation looks like below. It can be noticed that fetchUser(id) calls and returns the result of the API (/users/{id}) from another service.

Service Implementation making API calls with WebClient

In order to test UserService, there will be two tests. Firstly, by calling fetchUser, a call needs to be made to a specific endpoint (somehow a request needs to be captured to verify). Secondly, the return value of the fetchUser is what we expected (the return value of the API needs to be stubbed).

For these purposes, mockwebserver3 will be used. Add the following dependencies to pom.xml.

pom.xml

Set up and tear down of the MockWebServer can be done like this:

UserServiceTests.java (setup & teardown)

Capturing the Sent Request

The test below is to verify that calling fetchUser will invoke GET /users/1 endpoint. The sent request can be captured with MockWebServer.takeRequest().

UserServiceTests.java (test case)

Stubbing the return value of the WebClient

The test case below is to verify that fetchUser returns the expected values. The return value of the API can be stubbed with MockWebServer.enqueue().

UserServiceTests.java (test case)

--

--