I have a service layer using Spring Webflux and reactor and I am writing unit test for this. I was able to test the good response scenario but not sure how to test onErrorResume()
using StepVerifier. Also please let me know if there is a better way of handling exceptions in my controller(e.g: using switchIfEmpty()
)
Here is my controller method
public Mono<SomeType> getInfo(Integer id) {
return webClient
.get()
.uri(uriBuilder -> uriBuilder.path())
.header("", "")
.header("", "")
.header("", "")
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.retrieve()
.bodyToMono(POJO.class)
.onErrorResume(ex -> {
if (ex instanceof WebFaultException)
return Mono.error(ex);
return Mono.error(new WebFaultException(ex.getMessage(), "Error on API Call", HttpStatus.INTERNAL_SERVER_ERROR));
});
}
}
CodePudding user response:
You can mock the webclient and use Mockito.doThrow when webclientMock.get() is called.
YourWebClient webclientMock = mock(YourWebClient.class);
doThrow(RuntimeException.class)
.when(webclientMock)
.get();
// Call your method here
Exception exception = assertThrows(RuntimeException.class, () -> {
YourController.getInfo(someIntValue);
});
// If you chose to raise WebFaultException, addittionaly assert that the return values ( message, status) are the one you expected
CodePudding user response:
An alternate way to test your WebClient
code without having to mock the WebClient
class itself, as that can quickly become very messy, is to build your WebClient
with an ExchangeFunction
that returns whatever response or error you expect. I've found this to be a happy medium between mocking out the WebClient
and spinning up Wiremock
for unit tests.
@Test
void ourTest() {
ExchangeFunction exchangeFunction = mock(ExchangeFunction.class);
// this can be altered to return either happy or unhappy responses
given(exchangeFunction.exchange(any(ClientRequest.class))).willReturn(Mono.error(new RuntimeException()));
WebClient webClient = WebClient.builder()
.exchangeFunction(exchangeFunction)
.build();
// code under test - this should live in your service
Mono<String> mono = webClient.get()
.uri("http://someUrl.com")
.retrieve()
.bodyToMono(POJO.class)
.onErrorResume(ex -> {
if (ex instanceof WebFaultException)
return Mono.error(ex);
return Mono.error(new WebFaultException(ex.getMessage(), "Error on API Call", HttpStatus.INTERNAL_SERVER_ERROR));
});
StepVerifier.create(mono)
.expectError(RuntimeException.class)
.verify();
}