Browse Source
Prior to this commit, asking for a `Void` type using any of the `ClientResponse#bodyTo*` methods would immediately return an empty `Publisher` without consuming the response body. Not doing so can lead to HTTP connection pool inconsistencies and/or memory leaks, since: * a connection that still has a response body being written to it cannot be properly recycled in the connection pool * incoming `DataBuffer` might not be released This commit detects when `Void` types are asked as body types and in those cases does the following: 1. Subscribe to the response body `Publisher` to allow the connection to be returned to the connection pool 2. `cancel()` the body `Publisher` if the response body is not empty; in that case, we choose to close the connection vs. consume the whole response body Those changes imply that `ClientHttpResponse` and other related contracts don't need a `close()` method anymore. Issue: SPR-16018pull/1595/head
Brian Clozel
7 years ago
11 changed files with 122 additions and 152 deletions
@ -1,53 +0,0 @@
@@ -1,53 +0,0 @@
|
||||
package org.springframework.web.reactive.function.client; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import reactor.core.publisher.Mono; |
||||
import reactor.test.StepVerifier; |
||||
|
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.http.client.reactive.ClientHttpConnector; |
||||
import org.springframework.mock.http.client.reactive.test.MockClientHttpResponse; |
||||
|
||||
import static org.junit.Assert.assertFalse; |
||||
import static org.mockito.ArgumentMatchers.any; |
||||
import static org.mockito.BDDMockito.given; |
||||
import static org.mockito.Mockito.mock; |
||||
|
||||
/** |
||||
* Mock tests using a {@link ExchangeFunction} through {@link WebClient}. |
||||
* |
||||
* @author Brian Clozel |
||||
*/ |
||||
public class WebClientMockTests { |
||||
|
||||
private MockClientHttpResponse response; |
||||
|
||||
private ClientHttpConnector mockConnector; |
||||
|
||||
private WebClient webClient; |
||||
|
||||
@Before |
||||
public void setUp() throws Exception { |
||||
this.mockConnector = mock(ClientHttpConnector.class); |
||||
this.webClient = WebClient.builder().clientConnector(this.mockConnector).build(); |
||||
this.response = new MockClientHttpResponse(HttpStatus.OK); |
||||
this.response.setBody("example"); |
||||
|
||||
given(this.mockConnector.connect(any(), any(), any())).willReturn(Mono.just(this.response)); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldDisposeResponseManually() { |
||||
Mono<HttpHeaders> headers = this.webClient |
||||
.get().uri("/test") |
||||
.exchange() |
||||
.map(response -> response.headers().asHttpHeaders()); |
||||
StepVerifier.create(headers) |
||||
.expectNextCount(1) |
||||
.verifyComplete(); |
||||
assertFalse(this.response.isClosed()); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue