javaspringreactive-programmingspring-webfluxserver-response

How to get body as String from ServerResponse for test?


Say we have an instance of o.s.w.reactive.function.server.ServerResponse.

What is the proper way to fetch the contents of its body, in other words how to implement fetchBodyAsString function?

test(){
  ServerResponse response = getResponseFromService("mock data");

  String body = fetchBodyAsString(response);

  assertEquals("hello", body);
}

Could you also elaborate a bit on why does ServerResponse have methods for everything (cookies(), headers(), statusCode()), but the response body? I guess there should be a way to get the body with writeTo() method, although it is absolutely vague how to use it.


Solution

  • I was digging around for something similar for unit testing purposes, and stitched together the below code. It's in Kotlin, but should be relatively easy to translate to Java and solve your problem (though it definitely does seem a bit hacky).

        fun fetchBodyAsString(serverResponse: ServerResponse): String {
            val DEFAULT_CONTEXT: ServerResponse.Context = object : ServerResponse.Context {
                override fun messageWriters(): List<HttpMessageWriter<*>> {
                    return HandlerStrategies.withDefaults().messageWriters()
                }
    
                override fun viewResolvers(): List<ViewResolver> {
                    return Collections.emptyList()
                }
            }
    
            // Only way I could figure out how to get the ServerResponse body was to have it write to an exchange
            val request = MockServerHttpRequest.get("http://thisdoenstmatter.com").build()
            val exchange = MockServerWebExchange.from(request)
            serverResponse.writeTo(exchange, DEFAULT_CONTEXT).block()
            val response = exchange.response
            return response.bodyAsString.block()!!
        }
    

    Basically needed to create a fake MockServerWebExchange and have the ServerResponse write to it to translate it into a MockServerHttpResponse of which you can pull the response body out of fairly painlessly. This is definitely not elegant, but it works.

    Also note, I didn't test the above function itself, just that it compiles. It should work though as the function's inner code is exactly what we're using.

    As for your other questions about ServerResponse, I don't know the answers, but am curious about that as well!