Home > Software engineering >  Testing onErrorResume() Spring Webflux
Testing onErrorResume() Spring Webflux

Time:11-30

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();
    }

  • Related