I want to make a WebFlux
reactive call to a legacy SOAP service, using WebClient
.
The structure of the code is as follows:
AtomicReference<MyResponse> atomicReference = new AtomicReference<>();
webClient.post()
.uri(...)
.contentType(MediaType.XML)
.body(Mono.just(myRequest, MyRequest.class)
.retrieve()
.onStatus(
HttpStatus::isError,
clientResponse ->
clientResponse.bodyToMono(String.class)
.flatMap(errorResponseBody ->
Mono.error(new ResponseStatusException(
clientResponse.statusCode(), errorResponseBody))))
.bodyToMono(MyResponse.class)
.doOnSuccess( (MyResponse response) -> {
atomicReference.set(response);
})
.doOnError(ResponseStatusException.class, error -> {
//handle error
})
.subscribe();
What is the best way to mock such a reactive call?
Mocking a call to the non reactive WebServiceTemplate
is simple:
when(webServiceTemplate.marshalSendAndReceive(
ArgumentMatchers.eq("http://..."),
jaxbElement) // JaxbElement<MyRequest>
.thenReturn(myResponse);
Because the call is much simpler, and a the response is returned directly, it is straightforward to mock.
But to mock every stage in the WebClient
reactive chain would be tedious, brittle and error prone.
The problem is made more complex because - unless there is a simpler solution - the result is not returned from webClient, but rather passed to doOnSuccess
, which is deep in the chain. A WebClient.get()
call which returned a Mono
directly would be relatively simple to mock.
For the same reason, am unclear how MockWebServer
would work here, because it is necessary to verify what is passed to doOnSuccess
, not what the return value is.
Is there a straightforward solution?
Thanks