Testing Spring WebClient with MockWebServer

October 16, 2020

Spring Boot offers many convenience classes to simplify common test cases. For testing HTTP client code (testing a RestTemplate as opposed to testing a RestController), we can use the MockRestServiceServer in conjunction with the @RestClientTest annotation to mock a third party Web API.

// Testing with Spring Web and RestTemplate

@RestClientTest(TodoService.class)
class ExampleRestClientTest {

    @Autowired
    private TodoService service;

    @Autowired
    private MockRestServiceServer server;

    @Test
    void shouldReturnTodos() throws Exception {
        this.server.expect(requestTo("/todos")).andRespond(withSuccess("[]", MediaType.APPLICATION_JSON_VALUE));
        Collection<Todo> todos = this.service.fetchTodos();
        assertThat(todos).hasSize(0);
    }
}

This is well documented in the Spring Boot Reference Documentation.

Unfortunately the RestClientTest only supports RestTemplate, but not WebClient and thus cannot be used in a reactive Spring WebFlux application.
The recommended alternative for WebFlux is the use of a mock web server provided by the OkHttp library. The setup is only slightly more complex than before:

// Testing with Spring WebFlux and WebClient

class TodoServiceTest {

    private static MockWebServer mockWebServer;
    private static TodoService todoService;

    @BeforeAll
    static void beforeAll() {
        mockWebServer = new MockWebServer();
        todoService = new TodoService(WebClient.builder(), mockWebServer.url("/").url());
    }
    
    @AfterAll
    static void afterAll() throws IOException {
        mockWebServer.close();
    }

    @Test
    void shouldReturnTodoDtos() {
        mockWebServer.enqueue(
                new MockResponse()
                        .setResponseCode(200)
                        .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .setBody("[]")
        );
        assertThat(this.todoService.findTodos().collectList().block()).isEqualTo(Collections.emptyList());
    }
}

The full source code for this example is available in this Github project.

About the author: Rocco Schulz

Rocco loves clean air in the mountains and clean code in projects. He is interested in a multitude of sports activities, machine learning and various software engineering topics.

Comments
Join us