I noticed that Spring does not currently provide the same tools for testing WebClient-based reactive remote calls that the non-reactive RestTemplate API has, which from experience recently has lead to a little bit of frustration due to having to use more heavyweight/complicated non-Spring APIs to mock WebClient calls.

Since this felt relatively simple to implement, I went ahead and attempted to draft a reactive counterpart to the existing non-reactive MockRestServiceServer API.

This implementation is a shim that internally converts all requests and responses to the non-reactive counterparts. This enables the reactive API to use all the existing non-reactive request and response verification components without having to duplicate the entire API.

WebClientUtils in WebFlux has had to be updated to exclude Error types from the filter, otherwise AssertionErrors always end up being filtered out by the ExchangeFunctions conduit. I don't believe this should be an issue though, as the JavaDoc for Error types states that "no reasonable application should try to catch these types", which means that the ExchangeFunctions probably shouldn't have been allowing this through in the first place. Applied de-Morgans law to reduce the complexity of the expression a little.

The API itself attempts to be as similar to MockRestServiceServer as possible. For example:

val server = MockReactiveRestServiceServer.createServer()
val client = server.createWebClient()
val responseHeaders = HttpHeaders()

responseHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)

server
    .expect(requestTo("/actuator/health"))
    .andExpect(method(HttpMethod.GET))
    .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE))
    .andRespond(withSuccess()
        .headers(responseHeaders)
        .body("""{"status": "UP"}"""))

StepVerifier
    .create(client.get().uri("/actuator/health").retrieve().bodyToMono(String.class))
    .assertNext { assertThat(it).isEqualTo("""{"status": "UP"}""") }
    .verify()

Hope that contributions such as this are not considered out of place, or anything. If this is in the wrong place, please let me know!

Likewise if there are any other suggestions or feedback, I'd be happy to take those into account!

Comment From: snicoll

Thanks for the PR but getting to a state where it is feature complete would require quite a bit more work and we've already declining such an option in #19852. For consistency, I am going to close this. Sorry it took so long to process it.