[WebClient] @RestClientTest를 WebFlux에서 사용하기

2020. 7. 11. 18:58Java

RestTemplate을 사용하는 스프링 프로젝트에서는 외부 api를 mocking해서 테스트 할 때, 주로 @RestClientTest를 사용했다. 이에 관해서는 굉장히 좋은 글이 있으니 참고하면 좋을 것 같다.

문제

RestTemplate을 사용하지 않고 @RestClientTest를 쓰는 경우 아래와 같은 에러를 마주하게 된다.

스프링 진영에서는 @RestClientTestWebclient를 지원할 계획이 없다고 선언했다. 따라서 WebClient를 쓰는 경우 @RestClientTest를 사용하지 못한다.
하지만 대안으로 MockWebServer를 사용하라고 추천하고 있다.

해결

MockWebServer를 사용하면 @RestClientTest와 동일하게 서버를 mocking할 수 있다.

class WebClientTest {
    private MockWebServer server;

    private WebClient webClient;

    @BeforeEach
    void setUp() {
        ReactorClientHttpConnector connector = new ReactorClientHttpConnector();
        server = new MockWebServer();
        webClient = WebClient
            .builder()
            .clientConnector(connector)
            .baseUrl(server.url("/").toString())
            .build();
    }

    @AfterEach
    void shutdown() throws IOException {
        server.shutdown();
    }

    @DisplayName("Get 요청을 보낸 뒤, ResponseDto 를 응답")
    @Test
    void getRetrieveResponse() throws IOException {
        MockResponse mockResponse = new MockResponse()
            .addHeader("Authorization", "someTokenValue")
            .addHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
            .setResponseCode(HttpStatus.OK.value())
            .setBody("This is Response Body");

        server.enqueue(mockResponse);

        Mono<String> responseBody = webClient
            .get()
            .uri(GET_URL)
            .header("Authorization", "someTokenValue")
            .retrieve()
            .bodyToMono(String.class);

        StepVerifier.create(responseBody)
            .consumeNextWith(body -> assertThat(body).isEqualTo("This is Response Body"))
            .expectNextCount(0)
            .expectComplete()
            .verify();
    }
}

MockWebServer 객체를 생성하고, MockResponse를 필요한 만큼 생성해서 서버의 큐에 싣는 방식이다.
WebClient의 테스트 전략에 대한 설명은 여기서 자세히 확인할 수 있다.