Home > Blockchain >  Spring webflux junit test onErrorResume with Unauthorized exception
Spring webflux junit test onErrorResume with Unauthorized exception

Time:07-17

I have below service method which is using spring webflux to request webclient to get the response.

public Mono<String> fetch(String body, HttpHeaders headers, String correlationId) {
    Mono<String> response;
    try {
        response = postRequest(URI, headers, body);
    } catch (Exception exception) {
        throw new ExceptionHandler(HttpStatus.BAD_REQUEST, ErrorCode.REQUEST_ERROR);
    }
    return response;
}

private Mono<String> postRequest(String uri, HttpHeaders headers, String body) {
    return getStringMono(uri, headers, body).onErrorResume(exception -> {
        if (exception instanceof WebClientResponseException.Unauthorized) {
            accessTokenCache.invalidate(ACCESS_TOKEN);
            String updatedToken = accessTokenCache.getIfPresent(ACCESS_TOKEN);
            headers.replace(AUTHORIZATION, Collections.singletonList(updatedToken));
            return getStringMono(uri, headers, body);
        } else {
            log.info(exception.getMessage());
            throw new ExceptionHandler(HttpStatus.BAD_REQUEST, ErrorCode.REQUEST_ERROR);
        }
    });
}

private Mono<String> getStringMono(String uri, HttpHeaders headers, String body) {
    return webClient.post().uri(uri).headers(httpHeaders -> httpHeaders.addAll(headers))
            .body(Mono.just(body), String.class).retrieve().bodyToMono(String.class);
}

I want to test the above code using junit, and wrote the below testcase

@Test
    public void testUnauthorizedException() {
        RequestBodyUriSpec reqBodyUriMock = mock(WebClient.RequestBodyUriSpec.class);
        RequestBodySpec reqBodyMock = mock(WebClient.RequestBodySpec.class);
        RequestHeadersSpec reqHeaderMock = mock(WebClient.RequestHeadersSpec.class);
        ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class);
        when(webClient.post()).thenReturn(reqBodyUriMock);
        when(reqBodyUriMock.uri(ArgumentMatchers.<String>notNull())).thenReturn(reqBodyMock);
        when(reqBodyMock.headers(any())).thenReturn(requestBodySpec);
        when(reqBodyMock.body(any(), eq(String.class))).thenReturn(reqHeaderMock);
        when(reqHeaderMock.retrieve()).thenReturn(responseSpec);


        ExchangeFunction exchangeFunction = mock(ExchangeFunction.class);
        given(exchangeFunction.exchange(any(ClientRequest.class))).willReturn(Mono.error(WebClientResponseException.Unauthorized.create(HttpStatus.UNAUTHORIZED.value(), "Unauthorized", null, null, null)));

        when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
                .thenThrow(WebClientResponseException.Unauthorized.create(HttpStatus.UNAUTHORIZED.value(), "Unauthorized", null, null, null));

        ExceptionHandler exception = assertThrows(
                ExceptionHandler.class, () -> client.fetch(body, headers, correlationId));
        assertEquals(ErrorCode.REQUEST_ERROR, exception.getMessage());
    }

The test is not covering the Unauthorized exception if block instead its coming out and going into catch block of fetch method, how to refactor the test to cover Unauthorized exception if block?

CodePudding user response:

With the use of wiremock could able to stub the webclient, below is the working test

@Rule public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8888));

@Test
public void testUnauthorizedException() {
    String response = FileHelper.readFile(DATA   "Response.json");
    RequestBodyUriSpec reqBodyUriMock = mock(WebClient.RequestBodyUriSpec.class);
    RequestBodySpec reqBodyMock = mock(WebClient.RequestBodySpec.class);
    RequestHeadersSpec reqHeaderMock = mock(WebClient.RequestHeadersSpec.class);
    ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class);
    when(webClient.post()).thenReturn(reqBodyUriMock);
    when(reqBodyUriMock.uri(ArgumentMatchers.<String>notNull())).thenReturn(reqBodyMock);
    when(reqBodyMock.headers(any())).thenReturn(requestBodySpec);
    when(reqBodyMock.body(any(), eq(String.class))).thenReturn(reqHeaderMock);
    when(reqHeaderMock.retrieve()).thenReturn(responseSpec);
    
    when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
        .thenReturn(Mono.error(Unauthorized.create(HttpStatus.UNAUTHORIZED.value(), "Unauthorized", null, null, null)))
            .thenReturn(Mono.just(response));
            
    stubFor(post(URI)
            .willReturn(unauthorized()
                    .withStatus(401)
            ).willReturn(aResponse()
                    .withStatus(200)
                    .withBody("true"))
    );

    StepVerifier.create(client.fetch(body, headers, correlationId))
            .expectNextMatches(response -> response.equals(response))
            .expectComplete()
            .verify();
}
  • Related