WebFlux ServerResponse JSON Body Unit Testing

Creating a lightweight unit test that examines the body of a Spring WebFlux ServerResponse in isolation can be tricky. The following test class demonstrates one means of doing so:

import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.HttpMessageWriterView;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.WebHandler;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.List;

public class ServerResponseBodyTests {

    public static Mono<ServerResponse> testJsonServerResponse() {
        return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(Collections.singletonMap("key", "value")));
    }

    @Test
    public void testServerResponseBody() {
        WebHandler handler = exchange -> {
            ServerResponse serverResponse = testJsonServerResponse().block();
            return serverResponse.writeTo(exchange, JACKSON_CONTEXT);
        };

        WebTestClient.bindToWebHandler(handler).build()
                .get().uri("/")
                .exchange()
                .expectBody()
                .jsonPath("$.key").isEqualTo("value");
    }

    static final ServerResponse.Context JACKSON_CONTEXT = new ServerResponse.Context() {
        @Override
        public List<HttpMessageWriter<?>> messageWriters() {
            return Collections.singletonList(new HttpMessageWriterView(new Jackson2JsonEncoder()).getMessageWriter());
        }

        @Override
        public List<ViewResolver> viewResolvers() {
            return Collections.emptyList();
        }
    };

}

Note that the customized ServerResponse.Context is necessary because the test ServerResponse has a Content-Type header set to “application/json”. Testing without the Jackson encoder would result in an UnsupportedMediaTypeException being thrown.

Comments are closed.