From 5309757026f1a1bd6d8c82f3f9b7f8aacac1a214 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 26 Mar 2020 14:31:05 +0000 Subject: [PATCH] WebClientIntegrationTests refactoring - consistent test naming - grouping by category and logical ordering within category - consolidate overlapping tests - polishing See gh-24788 --- .../client/WebClientIntegrationTests.java | 1207 ++++++++--------- 1 file changed, 545 insertions(+), 662 deletions(-) diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java index 659004be48..62049e7d4f 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -106,343 +106,101 @@ class WebClientIntegrationTests { @ParameterizedWebClientTest - void shouldReceiveResponseHeaders(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response - .setHeader("Content-Type", "text/plain") - .setBody("Hello Spring!")); - - Mono result = this.webClient.get() - .uri("/greeting?name=Spring") - .exchange() - .map(response -> response.headers().asHttpHeaders()); - - StepVerifier.create(result) - .consumeNextWith( - httpHeaders -> { - assertThat(httpHeaders.getContentType()).isEqualTo(MediaType.TEXT_PLAIN); - assertThat(httpHeaders.getContentLength()).isEqualTo(13L); - }) - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); - }); - } - - @ParameterizedWebClientTest - void shouldReceivePlainText(ClientHttpConnector connector) { + void retrieve(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setBody("Hello Spring!")); Mono result = this.webClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") + .cookie("testkey", "testvalue") .header("X-Test-Header", "testvalue") .retrieve() .bodyToMono(String.class); StepVerifier.create(result) .expectNext("Hello Spring!") - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); - }); - } - - @ParameterizedWebClientTest - void shouldReceivePlainTextFlux(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setBody("Hello Spring!")); - - Flux result = this.webClient.get() - .uri("/greeting?name=Spring") - .header("X-Test-Header", "testvalue") - .exchange() - .flatMapMany(response -> response.bodyToFlux(String.class)); - - StepVerifier.create(result) - .expectNext("Hello Spring!") - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); - }); - } - - @ParameterizedWebClientTest - void shouldReceiveJsonAsString(ClientHttpConnector connector) { - startServer(connector); - - String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"; - prepareResponse(response -> response - .setHeader("Content-Type", "application/json").setBody(content)); - - Mono result = this.webClient.get() - .uri("/json").accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono(String.class); - - StepVerifier.create(result) - .expectNext(content) - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/json"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest // SPR-16715 - void shouldReceiveJsonAsTypeReferenceString(ClientHttpConnector connector) { - startServer(connector); - - String content = "{\"containerValue\":{\"fooValue\":\"bar\"}}"; - prepareResponse(response -> response - .setHeader("Content-Type", "application/json").setBody(content)); - - Mono> result = this.webClient.get() - .uri("/json").accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono(new ParameterizedTypeReference>() {}); - - StepVerifier.create(result) - .assertNext(valueContainer -> { - Foo foo = valueContainer.getContainerValue(); - assertThat(foo).isNotNull(); - assertThat(foo.getFooValue()).isEqualTo("bar"); - }) - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/json"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void exchangeShouldReceiveJsonAsResponseEntityString(ClientHttpConnector connector) { - startServer(connector); - - String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"; - prepareResponse(response -> response - .setHeader("Content-Type", "application/json").setBody(content)); - - Mono> result = this.webClient.get() - .uri("/json").accept(MediaType.APPLICATION_JSON) - .exchange() - .flatMap(response -> response.toEntity(String.class)); - - StepVerifier.create(result) - .consumeNextWith(entity -> { - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); - assertThat(entity.getBody()).isEqualTo(content); - }) - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/json"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void retrieveShouldReceiveJsonAsResponseEntityString(ClientHttpConnector connector) { - startServer(connector); - - String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"; - prepareResponse(response -> response - .setHeader("Content-Type", "application/json").setBody(content)); - - Mono> result = this.webClient.get() - .uri("/json").accept(MediaType.APPLICATION_JSON) - .retrieve() - .toEntity(String.class); - - StepVerifier.create(result) - .consumeNextWith(entity -> { - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); - assertThat(entity.getBody()).isEqualTo(content); - }) - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/json"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void exchangeBodilessEntity(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response - .setHeader("Content-Type", "application/json").setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")); - - Mono> result = this.webClient.get() - .uri("/json").accept(MediaType.APPLICATION_JSON) - .exchange() - .flatMap(ClientResponse::toBodilessEntity); - - StepVerifier.create(result) - .consumeNextWith(entity -> { - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); - assertThat(entity.getBody()).isNull(); - }) - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/json"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void retrieveBodilessEntity(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response - .setHeader("Content-Type", "application/json").setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")); - - Mono> result = this.webClient.get() - .uri("/json").accept(MediaType.APPLICATION_JSON) - .retrieve() - .toBodilessEntity(); - - StepVerifier.create(result) - .consumeNextWith(entity -> { - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); - assertThat(entity.getBody()).isNull(); - }) - .expectComplete().verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/json"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void retrieveEntityWithServerError(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setResponseCode(500) - .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); - - Mono> result = this.webClient.get() - .uri("/").accept(MediaType.APPLICATION_JSON) - .retrieve() - .toEntity(String.class); - - StepVerifier.create(result) - .expectError(WebClientResponseException.class) - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void retrieveBodilessEntityWithServerError(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setResponseCode(500) - .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); - - Mono> result = this.webClient.get() - .uri("/").accept(MediaType.APPLICATION_JSON) - .retrieve() - .toBodilessEntity(); - - StepVerifier.create(result) - .expectError(WebClientResponseException.class) - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void retrieveEntityWithServerErrorStatusHandler(ClientHttpConnector connector) { - startServer(connector); - - String content = "Internal Server error"; - prepareResponse(response -> response.setResponseCode(500) - .setHeader("Content-Type", "text/plain").setBody(content)); - - Mono> result = this.webClient.get() - .uri("/").accept(MediaType.APPLICATION_JSON) - .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.empty())// use normal response - .toEntity(String.class); - - StepVerifier.create(result) - .consumeNextWith(entity -> { - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - assertThat(entity.getBody()).isEqualTo(content); - }) .expectComplete() .verify(Duration.ofSeconds(3)); expectRequestCount(1); expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/"); + assertThat(request.getHeader(HttpHeaders.COOKIE)).isEqualTo("testkey=testvalue"); + assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); + assertThat(request.getPath()).isEqualTo("/greeting"); + }); + } + + @ParameterizedWebClientTest + void retrieveJson(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response + .setHeader("Content-Type", "application/json") + .setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")); + + Mono result = this.webClient.get() + .uri("/pojo") + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Pojo.class); + + StepVerifier.create(result) + .expectNext(new Pojo("foofoo", "barbar")) + .expectComplete() + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/pojo"); assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); }); } @ParameterizedWebClientTest - void exchangeShouldReceiveJsonAsResponseEntityList(ClientHttpConnector connector) { + void retrieveJsonWithParameterizedTypeReference(ClientHttpConnector connector) { startServer(connector); - String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]"; + String content = "{\"containerValue\":{\"bar\":\"barbar\",\"foo\":\"foofoo\"}}"; prepareResponse(response -> response .setHeader("Content-Type", "application/json").setBody(content)); - Mono>> result = this.webClient.get() + Mono> result = this.webClient.get() .uri("/json").accept(MediaType.APPLICATION_JSON) - .exchange() - .flatMap(response -> response.toEntityList(Pojo.class)); + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}); + + StepVerifier.create(result) + .assertNext(c -> assertThat(c.getContainerValue()).isEqualTo(new Pojo("foofoo", "barbar"))) + .expectComplete().verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/json"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void retrieveJsonAsResponseEntity(ClientHttpConnector connector) { + startServer(connector); + + String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"; + prepareResponse(response -> response + .setHeader("Content-Type", "application/json").setBody(content)); + + Mono> result = this.webClient.get() + .uri("/json").accept(MediaType.APPLICATION_JSON) + .retrieve() + .toEntity(String.class); StepVerifier.create(result) .consumeNextWith(entity -> { assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - assertThat(entity.getHeaders().getContentLength()).isEqualTo(58); - Pojo pojo1 = new Pojo("foo1", "bar1"); - Pojo pojo2 = new Pojo("foo2", "bar2"); - assertThat(entity.getBody()).isEqualTo(Arrays.asList(pojo1, pojo2)); + assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); + assertThat(entity.getBody()).isEqualTo(content); }) .expectComplete().verify(Duration.ofSeconds(3)); @@ -454,7 +212,62 @@ class WebClientIntegrationTests { } @ParameterizedWebClientTest - void retrieveShouldReceiveJsonAsResponseEntityList(ClientHttpConnector connector) { + void retrieveJsonAsBodilessEntity(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response + .setHeader("Content-Type", "application/json").setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")); + + Mono> result = this.webClient.get() + .uri("/json").accept(MediaType.APPLICATION_JSON) + .retrieve() + .toBodilessEntity(); + + StepVerifier.create(result) + .consumeNextWith(entity -> { + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); + assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); + assertThat(entity.getBody()).isNull(); + }) + .expectComplete().verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/json"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void retrieveJsonArray(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response + .setHeader("Content-Type", "application/json") + .setBody("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]")); + + Flux result = this.webClient.get() + .uri("/pojos") + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToFlux(Pojo.class); + + StepVerifier.create(result) + .consumeNextWith(p -> assertThat(p.getBar()).isEqualTo("bar1")) + .consumeNextWith(p -> assertThat(p.getBar()).isEqualTo("bar2")) + .expectComplete() + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/pojos"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void retrieveJsonArrayAsResponseEntity(ClientHttpConnector connector) { startServer(connector); String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]"; @@ -485,40 +298,17 @@ class WebClientIntegrationTests { } @ParameterizedWebClientTest - void retrieveEntityListWithServerError(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setResponseCode(500) - .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); - - Mono>> result = this.webClient.get() - .uri("/").accept(MediaType.APPLICATION_JSON) - .retrieve() - .toEntityList(String.class); - - StepVerifier.create(result) - .expectError(WebClientResponseException.class) - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void shouldReceiveJsonAsFluxString(ClientHttpConnector connector) { + void retrieveJsonAsSerializedText(ClientHttpConnector connector) { startServer(connector); String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"; prepareResponse(response -> response .setHeader("Content-Type", "application/json").setBody(content)); - Flux result = this.webClient.get() + Mono result = this.webClient.get() .uri("/json").accept(MediaType.APPLICATION_JSON) .retrieve() - .bodyToFlux(String.class); + .bodyToMono(String.class); StepVerifier.create(result) .expectNext(content) @@ -532,192 +322,24 @@ class WebClientIntegrationTests { } @ParameterizedWebClientTest - void shouldReceiveJsonAsPojo(ClientHttpConnector connector) { + void retrieveJsonNull(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response - .setHeader("Content-Type", "application/json") - .setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")); + .setResponseCode(200) + .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setBody("null")); - Mono result = this.webClient.get() - .uri("/pojo") - .accept(MediaType.APPLICATION_JSON) + Mono result = this.webClient.get() + .uri("/null") .retrieve() - .bodyToMono(Pojo.class); + .bodyToMono(Map.class); - StepVerifier.create(result) - .consumeNextWith(p -> assertThat(p.getBar()).isEqualTo("barbar")) - .expectComplete() - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/pojo"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void shouldReceiveJsonAsFluxPojo(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response - .setHeader("Content-Type", "application/json") - .setBody("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]")); - - Flux result = this.webClient.get() - .uri("/pojos") - .accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToFlux(Pojo.class); - - StepVerifier.create(result) - .consumeNextWith(p -> assertThat(p.getBar()).isEqualTo("bar1")) - .consumeNextWith(p -> assertThat(p.getBar()).isEqualTo("bar2")) - .expectComplete() - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/pojos"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void shouldSendPojoAsJson(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setHeader("Content-Type", "application/json") - .setBody("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}")); - - Mono result = this.webClient.post() - .uri("/pojo/capitalize") - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(new Pojo("foofoo", "barbar")) - .retrieve() - .bodyToMono(Pojo.class); - - StepVerifier.create(result) - .consumeNextWith(p -> assertThat(p.getBar()).isEqualTo("BARBAR")) - .expectComplete() - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/pojo/capitalize"); - assertThat(request.getBody().readUtf8()).isEqualTo("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}"); - assertThat(request.getHeader(HttpHeaders.CONTENT_LENGTH)).isEqualTo("31"); - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); - assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json"); - }); - } - - @ParameterizedWebClientTest - void shouldSendCookies(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response - .setHeader("Content-Type", "text/plain").setBody("test")); - - Mono result = this.webClient.get() - .uri("/test") - .cookie("testkey", "testvalue") - .retrieve() - .bodyToMono(String.class); - - StepVerifier.create(result) - .expectNext("test") - .expectComplete() - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getPath()).isEqualTo("/test"); - assertThat(request.getHeader(HttpHeaders.COOKIE)).isEqualTo("testkey=testvalue"); - }); - } - - @ParameterizedWebClientTest // SPR-16246 - void shouldSendLargeTextFile(ClientHttpConnector connector) throws Exception { - startServer(connector); - - prepareResponse(response -> {}); - - Resource resource = new ClassPathResource("largeTextFile.txt", getClass()); - Flux body = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 4096); - - Mono result = this.webClient.post() - .uri("/") - .body(body, DataBuffer.class) - .retrieve() - .bodyToMono(Void.class); - - StepVerifier.create(result) - .expectComplete() - .verify(Duration.ofSeconds(5)); - - expectRequest(request -> { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - try { - request.getBody().copyTo(bos); - String actual = bos.toString("UTF-8"); - String expected = new String(Files.readAllBytes(resource.getFile().toPath()), StandardCharsets.UTF_8); - assertThat(actual).isEqualTo(expected); - } - catch (IOException ex) { - throw new UncheckedIOException(ex); - } - }); - } - - @ParameterizedWebClientTest - void shouldReceive404Response(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setResponseCode(404) - .setHeader("Content-Type", "text/plain").setBody("Not Found")); - - Mono result = this.webClient.get().uri("/greeting?name=Spring").exchange(); - - StepVerifier.create(result) - .consumeNextWith(response -> assertThat(response.statusCode()).isEqualTo(HttpStatus.NOT_FOUND)) - .expectComplete() - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); - }); - } - - @ParameterizedWebClientTest - void shouldGetErrorSignalOn404(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setResponseCode(404) - .setHeader("Content-Type", "text/plain").setBody("Not Found")); - - Mono result = this.webClient.get() - .uri("/greeting?name=Spring") - .retrieve() - .bodyToMono(String.class); - - StepVerifier.create(result) - .expectError(WebClientResponseException.class) - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); - }); + StepVerifier.create(result).verifyComplete(); } @ParameterizedWebClientTest // SPR-15946 - void shouldGetErrorSignalOnEmptyErrorResponse(ClientHttpConnector connector) { + void retrieve404(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setResponseCode(404) @@ -739,14 +361,37 @@ class WebClientIntegrationTests { } @ParameterizedWebClientTest - void shouldGetInternalServerErrorSignal(ClientHttpConnector connector) { + void retrieve404WithBody(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response.setResponseCode(404) + .setHeader("Content-Type", "text/plain").setBody("Not Found")); + + Mono result = this.webClient.get() + .uri("/greeting") + .retrieve() + .bodyToMono(String.class); + + StepVerifier.create(result) + .expectError(WebClientResponseException.class) + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); + assertThat(request.getPath()).isEqualTo("/greeting"); + }); + } + + @ParameterizedWebClientTest + void retrieve500(ClientHttpConnector connector) { startServer(connector); String errorMessage = "Internal Server error"; prepareResponse(response -> response.setResponseCode(500) .setHeader("Content-Type", "text/plain").setBody(errorMessage)); - String path = "/greeting?name=Spring"; + String path = "/greeting"; Mono result = this.webClient.get() .uri(path) .retrieve() @@ -777,33 +422,76 @@ class WebClientIntegrationTests { } @ParameterizedWebClientTest - void shouldSupportUnknownStatusCode(ClientHttpConnector connector) { + void retrieve500AsEntity(ClientHttpConnector connector) { startServer(connector); - int errorStatus = 555; - assertThat((Object) HttpStatus.resolve(errorStatus)).isNull(); - String errorMessage = "Something went wrong"; - prepareResponse(response -> response.setResponseCode(errorStatus) - .setHeader("Content-Type", "text/plain").setBody(errorMessage)); + prepareResponse(response -> response.setResponseCode(500) + .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); - Mono result = this.webClient.get() - .uri("/unknownPage") - .exchange(); + Mono> result = this.webClient.get() + .uri("/").accept(MediaType.APPLICATION_JSON) + .retrieve() + .toEntity(String.class); StepVerifier.create(result) - .consumeNextWith(response -> assertThat(response.rawStatusCode()).isEqualTo(555)) - .expectComplete() + .expectError(WebClientResponseException.class) .verify(Duration.ofSeconds(3)); expectRequestCount(1); expectRequest(request -> { - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/unknownPage"); + assertThat(request.getPath()).isEqualTo("/"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); }); } @ParameterizedWebClientTest - void shouldGetErrorSignalWhenRetrievingUnknownStatusCode(ClientHttpConnector connector) { + void retrieve500AsEntityList(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response.setResponseCode(500) + .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); + + Mono>> result = this.webClient.get() + .uri("/").accept(MediaType.APPLICATION_JSON) + .retrieve() + .toEntityList(String.class); + + StepVerifier.create(result) + .expectError(WebClientResponseException.class) + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void retrieve500AsBodilessEntity(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response.setResponseCode(500) + .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); + + Mono> result = this.webClient.get() + .uri("/").accept(MediaType.APPLICATION_JSON) + .retrieve() + .toBodilessEntity(); + + StepVerifier.create(result) + .expectError(WebClientResponseException.class) + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void retrieve555UnknownStatus(ClientHttpConnector connector) { startServer(connector); int errorStatus = 555; @@ -837,14 +525,77 @@ class WebClientIntegrationTests { } @ParameterizedWebClientTest - void shouldApplyCustomStatusHandler(ClientHttpConnector connector) { + void postPojoAsJson(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response.setHeader("Content-Type", "application/json") + .setBody("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}")); + + Mono result = this.webClient.post() + .uri("/pojo/capitalize") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(new Pojo("foofoo", "barbar")) + .retrieve() + .bodyToMono(Pojo.class); + + StepVerifier.create(result) + .consumeNextWith(p -> assertThat(p.getBar()).isEqualTo("BARBAR")) + .expectComplete() + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/pojo/capitalize"); + assertThat(request.getBody().readUtf8()).isEqualTo("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}"); + assertThat(request.getHeader(HttpHeaders.CONTENT_LENGTH)).isEqualTo("31"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest // SPR-16246 + void postLargeTextFile(ClientHttpConnector connector) throws Exception { + startServer(connector); + + prepareResponse(response -> {}); + + Resource resource = new ClassPathResource("largeTextFile.txt", getClass()); + Flux body = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 4096); + + Mono result = this.webClient.post() + .uri("/") + .body(body, DataBuffer.class) + .retrieve() + .bodyToMono(Void.class); + + StepVerifier.create(result) + .expectComplete() + .verify(Duration.ofSeconds(5)); + + expectRequest(request -> { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + request.getBody().copyTo(bos); + String actual = bos.toString("UTF-8"); + String expected = new String(Files.readAllBytes(resource.getFile().toPath()), StandardCharsets.UTF_8); + assertThat(actual).isEqualTo(expected); + } + catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + } + + @ParameterizedWebClientTest + void statusHandler(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setResponseCode(500) .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); Mono result = this.webClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") .retrieve() .onStatus(HttpStatus::is5xxServerError, response -> Mono.just(new MyException("500 error!"))) .bodyToMono(String.class); @@ -856,43 +607,19 @@ class WebClientIntegrationTests { expectRequestCount(1); expectRequest(request -> { assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); + assertThat(request.getPath()).isEqualTo("/greeting"); }); } @ParameterizedWebClientTest - void shouldApplyCustomRawStatusHandler(ClientHttpConnector connector) { + void statusHandlerParameterizedTypeReference(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setResponseCode(500) .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); Mono result = this.webClient.get() - .uri("/greeting?name=Spring") - .retrieve() - .onRawStatus(value -> value >= 500 && value < 600, response -> Mono.just(new MyException("500 error!"))) - .bodyToMono(String.class); - - StepVerifier.create(result) - .expectError(MyException.class) - .verify(Duration.ofSeconds(3)); - - expectRequestCount(1); - expectRequest(request -> { - assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); - }); - } - - @ParameterizedWebClientTest - void shouldApplyCustomStatusHandlerParameterizedTypeReference(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setResponseCode(500) - .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); - - Mono result = this.webClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") .retrieve() .onStatus(HttpStatus::is5xxServerError, response -> Mono.just(new MyException("500 error!"))) .bodyToMono(new ParameterizedTypeReference() {}); @@ -904,19 +631,71 @@ class WebClientIntegrationTests { expectRequestCount(1); expectRequest(request -> { assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); + assertThat(request.getPath()).isEqualTo("/greeting"); }); } @ParameterizedWebClientTest - void emptyStatusHandlerShouldReturnBody(ClientHttpConnector connector) { + void statusHandlerWithErrorBodyTransformation(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response + .setResponseCode(500) + .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}") + ); + + Mono result = this.webClient.get() + .uri("/json") + .retrieve() + .onStatus(HttpStatus::isError, + response -> response.bodyToMono(Pojo.class) + .flatMap(pojo -> Mono.error(new MyException(pojo.getFoo()))) + ) + .bodyToMono(String.class); + + StepVerifier.create(result) + .consumeErrorWith(throwable -> { + assertThat(throwable).isInstanceOf(MyException.class); + MyException error = (MyException) throwable; + assertThat(error.getMessage()).isEqualTo("foofoo"); + }) + .verify(); + } + + @ParameterizedWebClientTest + void statusHandlerRawStatus(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setResponseCode(500) .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); Mono result = this.webClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") + .retrieve() + .onRawStatus(value -> value >= 500 && value < 600, response -> Mono.just(new MyException("500 error!"))) + .bodyToMono(String.class); + + StepVerifier.create(result) + .expectError(MyException.class) + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); + assertThat(request.getPath()).isEqualTo("/greeting"); + }); + } + + @ParameterizedWebClientTest + void statusHandlerSuppressedErrorSignal(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response.setResponseCode(500) + .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); + + Mono result = this.webClient.get() + .uri("/greeting") .retrieve() .onStatus(HttpStatus::is5xxServerError, response -> Mono.empty()) .bodyToMono(String.class); @@ -928,19 +707,19 @@ class WebClientIntegrationTests { expectRequestCount(1); expectRequest(request -> { assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); + assertThat(request.getPath()).isEqualTo("/greeting"); }); } @ParameterizedWebClientTest - void emptyStatusHandlerShouldReturnBodyFlux(ClientHttpConnector connector) { + void statusHandlerSuppressedErrorSignalWithFlux(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setResponseCode(500) .setHeader("Content-Type", "text/plain").setBody("Internal Server error")); Flux result = this.webClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") .retrieve() .onStatus(HttpStatus::is5xxServerError, response -> Mono.empty()) .bodyToFlux(String.class); @@ -952,36 +731,228 @@ class WebClientIntegrationTests { expectRequestCount(1); expectRequest(request -> { assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); + assertThat(request.getPath()).isEqualTo("/greeting"); }); } @ParameterizedWebClientTest - void shouldReceiveNotFoundEntity(ClientHttpConnector connector) { + void statusHandlerSuppressedErrorSignalWithEntity(ClientHttpConnector connector) { + startServer(connector); + + String content = "Internal Server error"; + prepareResponse(response -> response.setResponseCode(500) + .setHeader("Content-Type", "text/plain").setBody(content)); + + Mono> result = this.webClient.get() + .uri("/").accept(MediaType.APPLICATION_JSON) + .retrieve() + .onStatus(HttpStatus::is5xxServerError, response -> Mono.empty())// use normal response + .toEntity(String.class); + + StepVerifier.create(result) + .consumeNextWith(entity -> { + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(entity.getBody()).isEqualTo(content); + }) + .expectComplete() + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void exchangeForPlainText(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response.setBody("Hello Spring!")); + + Mono result = this.webClient.get() + .uri("/greeting") + .header("X-Test-Header", "testvalue") + .exchange() + .flatMap(response -> response.bodyToMono(String.class)); + + StepVerifier.create(result) + .expectNext("Hello Spring!") + .expectComplete().verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); + assertThat(request.getPath()).isEqualTo("/greeting"); + }); + } + + @ParameterizedWebClientTest + void exchangeForJsonAsResponseEntity(ClientHttpConnector connector) { + startServer(connector); + + String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"; + prepareResponse(response -> response + .setHeader("Content-Type", "application/json").setBody(content)); + + Mono> result = this.webClient.get() + .uri("/json").accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMap(response -> response.toEntity(Pojo.class)); + + StepVerifier.create(result) + .consumeNextWith(entity -> { + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); + assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); + assertThat(entity.getBody()).isEqualTo(new Pojo("foofoo", "barbar")); + }) + .expectComplete().verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/json"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void exchangeForJsonAsBodilessEntity(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response + .setHeader("Content-Type", "application/json").setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")); + + Mono> result = this.webClient.get() + .uri("/json").accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMap(ClientResponse::toBodilessEntity); + + StepVerifier.create(result) + .consumeNextWith(entity -> { + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); + assertThat(entity.getHeaders().getContentLength()).isEqualTo(31); + assertThat(entity.getBody()).isNull(); + }) + .expectComplete().verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/json"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void exchangeForJsonArrayAsResponseEntity(ClientHttpConnector connector) { + startServer(connector); + + String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]"; + prepareResponse(response -> response + .setHeader("Content-Type", "application/json").setBody(content)); + + Mono>> result = this.webClient.get() + .uri("/json").accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMap(response -> response.toEntityList(Pojo.class)); + + StepVerifier.create(result) + .consumeNextWith(entity -> { + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); + assertThat(entity.getHeaders().getContentLength()).isEqualTo(58); + Pojo pojo1 = new Pojo("foo1", "bar1"); + Pojo pojo2 = new Pojo("foo2", "bar2"); + assertThat(entity.getBody()).isEqualTo(Arrays.asList(pojo1, pojo2)); + }) + .expectComplete().verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getPath()).isEqualTo("/json"); + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json"); + }); + } + + @ParameterizedWebClientTest + void exchangeForEmptyBodyAsVoidEntity(ClientHttpConnector connector) { + startServer(connector); + + prepareResponse(response -> response.setHeader("Content-Length", "0").setBody("")); + + Mono> result = this.webClient.get() + .uri("/noContent") + .exchange() + .flatMap(response -> response.toEntity(Void.class)); + + StepVerifier.create(result) + .assertNext(r -> assertThat(r.getStatusCode().is2xxSuccessful()).isTrue()) + .verifyComplete(); + } + + @ParameterizedWebClientTest + void exchangeFor404(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setResponseCode(404) .setHeader("Content-Type", "text/plain").setBody("Not Found")); - Mono> result = this.webClient.get() - .uri("/greeting?name=Spring") - .exchange() - .flatMap(response -> response.toEntity(String.class)); + Mono result = this.webClient.get().uri("/greeting").exchange(); StepVerifier.create(result) - .consumeNextWith(response -> assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND)) + .consumeNextWith(response -> assertThat(response.statusCode()).isEqualTo(HttpStatus.NOT_FOUND)) .expectComplete() .verify(Duration.ofSeconds(3)); expectRequestCount(1); expectRequest(request -> { assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); - assertThat(request.getPath()).isEqualTo("/greeting?name=Spring"); + assertThat(request.getPath()).isEqualTo("/greeting"); }); } @ParameterizedWebClientTest - void shouldApplyExchangeFilter(ClientHttpConnector connector) { + void exchangeForUnknownStatusCode(ClientHttpConnector connector) { + startServer(connector); + + int errorStatus = 555; + assertThat((Object) HttpStatus.resolve(errorStatus)).isNull(); + String errorMessage = "Something went wrong"; + prepareResponse(response -> response.setResponseCode(errorStatus) + .setHeader("Content-Type", "text/plain").setBody(errorMessage)); + + Mono result = this.webClient.get() + .uri("/unknownPage") + .exchange(); + + StepVerifier.create(result) + .consumeNextWith(response -> assertThat(response.rawStatusCode()).isEqualTo(555)) + .expectComplete() + .verify(Duration.ofSeconds(3)); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*"); + assertThat(request.getPath()).isEqualTo("/unknownPage"); + }); + } + + @ParameterizedWebClientTest // SPR-15782 + void exchangeWithRelativeUrl(ClientHttpConnector connector) { + startServer(connector); + + String uri = "/api/v4/groups/1"; + Mono responseMono = WebClient.builder().build().get().uri(uri).exchange(); + + StepVerifier.create(responseMono) + .expectErrorMessage("URI is not absolute: " + uri) + .verify(Duration.ofSeconds(5)); + } + + @ParameterizedWebClientTest + void filter(ClientHttpConnector connector) { startServer(connector); prepareResponse(response -> response.setHeader("Content-Type", "text/plain") @@ -996,7 +967,7 @@ class WebClientIntegrationTests { .build(); Mono result = filteredClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") .retrieve() .bodyToMono(String.class); @@ -1010,7 +981,7 @@ class WebClientIntegrationTests { } @ParameterizedWebClientTest - void shouldApplyErrorHandlingFilter(ClientHttpConnector connector) { + void filterForErrorHandling(ClientHttpConnector connector) { startServer(connector); ExchangeFilterFunction filter = ExchangeFilterFunction.ofResponseProcessor( @@ -1029,7 +1000,7 @@ class WebClientIntegrationTests { .setHeader("Content-Type", "text/plain").setBody("Hello Spring!")); Mono result = filteredClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") .retrieve() .bodyToMono(String.class); @@ -1043,7 +1014,7 @@ class WebClientIntegrationTests { .setBody("Hello Spring!")); result = filteredClient.get() - .uri("/greeting?name=Spring") + .uri("/greeting") .retrieve().bodyToMono(String.class); StepVerifier.create(result) @@ -1053,80 +1024,6 @@ class WebClientIntegrationTests { expectRequestCount(2); } - @ParameterizedWebClientTest - void shouldReceiveEmptyResponse(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response.setHeader("Content-Length", "0").setBody("")); - - Mono> result = this.webClient.get() - .uri("/noContent") - .exchange() - .flatMap(response -> response.toEntity(Void.class)); - - StepVerifier.create(result).assertNext(r -> - assertThat(r.getStatusCode().is2xxSuccessful()).isTrue() - ).verifyComplete(); - } - - @ParameterizedWebClientTest // SPR-15782 - void shouldFailWithRelativeUrls(ClientHttpConnector connector) { - startServer(connector); - - String uri = "/api/v4/groups/1"; - Mono responseMono = WebClient.builder().build().get().uri(uri).exchange(); - - StepVerifier.create(responseMono) - .expectErrorMessage("URI is not absolute: " + uri) - .verify(Duration.ofSeconds(5)); - } - - @ParameterizedWebClientTest - void nullJsonResponseShouldBeReadAsEmpty(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response - .setResponseCode(200) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody("null")); - - Mono result = this.webClient.get() - .uri("/null") - .retrieve() - .bodyToMono(Map.class); - - StepVerifier.create(result) - .verifyComplete(); - } - - @ParameterizedWebClientTest - void mapBodyInOnStatus(ClientHttpConnector connector) { - startServer(connector); - - prepareResponse(response -> response - .setResponseCode(500) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody("{\"fooValue\":\"bar\"}") - ); - - Mono result = this.webClient.get() - .uri("/json") - .retrieve() - .onStatus(HttpStatus::isError, response -> - response.bodyToMono(Foo.class) - .flatMap(foo -> Mono.error(new MyException(foo.getFooValue()))) - ) - .bodyToMono(String.class); - - StepVerifier.create(result) - .consumeErrorWith(throwable -> { - assertThat(throwable).isInstanceOf(MyException.class); - MyException error = (MyException) throwable; - assertThat(error.getMessage()).isEqualTo("bar"); - }) - .verify(); - } - private void prepareResponse(Consumer consumer) { MockResponse response = new MockResponse(); @@ -1171,18 +1068,4 @@ class WebClientIntegrationTests { } } - - static class Foo { - - private String fooValue; - - public String getFooValue() { - return fooValue; - } - - public void setFooValue(String fooValue) { - this.fooValue = fooValue; - } - } - }