Polish "Improve documentation of TestRestTemplate's fault tolerance"

See gh-26227
This commit is contained in:
Andy Wilkinson 2021-05-17 11:07:23 +01:00
parent a6fa8addb9
commit be807bab12
2 changed files with 52 additions and 57 deletions

View File

@ -7606,7 +7606,9 @@ include::{test-examples}/test/system/OutputCaptureTests.java[tag=test]
==== TestRestTemplate
`TestRestTemplate` is a convenience alternative to Spring's `RestTemplate` that is useful in integration tests.
You can get a vanilla template or one that sends Basic HTTP authentication (with a username and password).
In either case, the template behaves in a test-friendly way by not throwing exceptions on server-side errors.
In either case, the template is fault tolerant.
This means that it behaves in a test-friendly way by not throwing exceptions on 4xx and 5xx errors.
Instead, such errors can be detected via the returned `ResponseEntity` and its status code.
TIP: Spring Framework 5.0 provides a new `WebTestClient` that works for <<boot-features-testing-spring-boot-applications-testing-autoconfigured-webflux-tests, WebFlux integration tests>> and both <<boot-features-testing-spring-boot-applications-testing-with-running-server, WebFlux and MVC end-to-end testing>>.
It provides a fluent API for assertions, unlike `TestRestTemplate`.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
@ -49,16 +49,19 @@ import org.springframework.util.Assert;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriTemplateHandler;
/**
* Convenient alternative of {@link RestTemplate} that is suitable for integration tests.
* They are fault tolerant, and optionally can carry Basic authentication headers. If
* Apache Http Client 4.3.2 or better is available (recommended) it will be used as the
* client, and by default configured to ignore cookies and redirects.
* {@code TestRestTemplate} is fault tolerant. This means that 4xx and 5xx do not result
* in an exception being thrown and can instead be detected via the {@link ResponseEntity
* response entity} and its {@link ResponseEntity#getStatusCode() status code}.
* <p>
* A {@code TestRestTemplate} can optionally carry Basic authentication headers. If Apache
* Http Client 4.3.2 or better is available (recommended) it will be used as the client,
* and by default configured to ignore cookies and redirects.
* <p>
* Note: To prevent injection problems this class intentionally does not extend
* {@link RestTemplate}. If you need access to the underlying {@link RestTemplate} use
@ -177,7 +180,7 @@ public class TestRestTemplate {
* @return the converted object
* @see RestTemplate#getForObject(String, Class, Object...)
*/
public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException {
public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) {
return this.restTemplate.getForObject(url, responseType, urlVariables);
}
@ -193,8 +196,7 @@ public class TestRestTemplate {
* @return the converted object
* @see RestTemplate#getForObject(String, Class, Object...)
*/
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> urlVariables)
throws RestClientException {
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> urlVariables) {
return this.restTemplate.getForObject(url, responseType, urlVariables);
}
@ -207,7 +209,7 @@ public class TestRestTemplate {
* @return the converted object
* @see RestTemplate#getForObject(java.net.URI, java.lang.Class)
*/
public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException {
public <T> T getForObject(URI url, Class<T> responseType) {
return this.restTemplate.getForObject(applyRootUriIfNecessary(url), responseType);
}
@ -224,8 +226,7 @@ public class TestRestTemplate {
* @see RestTemplate#getForEntity(java.lang.String, java.lang.Class,
* java.lang.Object[])
*/
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... urlVariables)
throws RestClientException {
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... urlVariables) {
return this.restTemplate.getForEntity(url, responseType, urlVariables);
}
@ -241,8 +242,7 @@ public class TestRestTemplate {
* @return the converted object
* @see RestTemplate#getForEntity(java.lang.String, java.lang.Class, java.util.Map)
*/
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> urlVariables)
throws RestClientException {
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> urlVariables) {
return this.restTemplate.getForEntity(url, responseType, urlVariables);
}
@ -255,7 +255,7 @@ public class TestRestTemplate {
* @return the converted object
* @see RestTemplate#getForEntity(java.net.URI, java.lang.Class)
*/
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException {
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) {
return this.restTemplate.getForEntity(applyRootUriIfNecessary(url), responseType);
}
@ -268,7 +268,7 @@ public class TestRestTemplate {
* @return all HTTP headers of that resource
* @see RestTemplate#headForHeaders(java.lang.String, java.lang.Object[])
*/
public HttpHeaders headForHeaders(String url, Object... urlVariables) throws RestClientException {
public HttpHeaders headForHeaders(String url, Object... urlVariables) {
return this.restTemplate.headForHeaders(url, urlVariables);
}
@ -281,7 +281,7 @@ public class TestRestTemplate {
* @return all HTTP headers of that resource
* @see RestTemplate#headForHeaders(java.lang.String, java.util.Map)
*/
public HttpHeaders headForHeaders(String url, Map<String, ?> urlVariables) throws RestClientException {
public HttpHeaders headForHeaders(String url, Map<String, ?> urlVariables) {
return this.restTemplate.headForHeaders(url, urlVariables);
}
@ -291,7 +291,7 @@ public class TestRestTemplate {
* @return all HTTP headers of that resource
* @see RestTemplate#headForHeaders(java.net.URI)
*/
public HttpHeaders headForHeaders(URI url) throws RestClientException {
public HttpHeaders headForHeaders(URI url) {
return this.restTemplate.headForHeaders(applyRootUriIfNecessary(url));
}
@ -312,7 +312,7 @@ public class TestRestTemplate {
* @see RestTemplate#postForLocation(java.lang.String, java.lang.Object,
* java.lang.Object[])
*/
public URI postForLocation(String url, Object request, Object... urlVariables) throws RestClientException {
public URI postForLocation(String url, Object request, Object... urlVariables) {
return this.restTemplate.postForLocation(url, request, urlVariables);
}
@ -333,7 +333,7 @@ public class TestRestTemplate {
* @see RestTemplate#postForLocation(java.lang.String, java.lang.Object,
* java.util.Map)
*/
public URI postForLocation(String url, Object request, Map<String, ?> urlVariables) throws RestClientException {
public URI postForLocation(String url, Object request, Map<String, ?> urlVariables) {
return this.restTemplate.postForLocation(url, request, urlVariables);
}
@ -350,7 +350,7 @@ public class TestRestTemplate {
* @see HttpEntity
* @see RestTemplate#postForLocation(java.net.URI, java.lang.Object)
*/
public URI postForLocation(URI url, Object request) throws RestClientException {
public URI postForLocation(URI url, Object request) {
return this.restTemplate.postForLocation(applyRootUriIfNecessary(url), request);
}
@ -372,8 +372,7 @@ public class TestRestTemplate {
* @see RestTemplate#postForObject(java.lang.String, java.lang.Object,
* java.lang.Class, java.lang.Object[])
*/
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... urlVariables)
throws RestClientException {
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... urlVariables) {
return this.restTemplate.postForObject(url, request, responseType, urlVariables);
}
@ -395,8 +394,7 @@ public class TestRestTemplate {
* @see RestTemplate#postForObject(java.lang.String, java.lang.Object,
* java.lang.Class, java.util.Map)
*/
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> urlVariables)
throws RestClientException {
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> urlVariables) {
return this.restTemplate.postForObject(url, request, responseType, urlVariables);
}
@ -414,7 +412,7 @@ public class TestRestTemplate {
* @see HttpEntity
* @see RestTemplate#postForObject(java.net.URI, java.lang.Object, java.lang.Class)
*/
public <T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException {
public <T> T postForObject(URI url, Object request, Class<T> responseType) {
return this.restTemplate.postForObject(applyRootUriIfNecessary(url), request, responseType);
}
@ -437,7 +435,7 @@ public class TestRestTemplate {
* java.lang.Class, java.lang.Object[])
*/
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType,
Object... urlVariables) throws RestClientException {
Object... urlVariables) {
return this.restTemplate.postForEntity(url, request, responseType, urlVariables);
}
@ -460,7 +458,7 @@ public class TestRestTemplate {
* java.lang.Class, java.util.Map)
*/
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType,
Map<String, ?> urlVariables) throws RestClientException {
Map<String, ?> urlVariables) {
return this.restTemplate.postForEntity(url, request, responseType, urlVariables);
}
@ -478,8 +476,7 @@ public class TestRestTemplate {
* @see HttpEntity
* @see RestTemplate#postForEntity(java.net.URI, java.lang.Object, java.lang.Class)
*/
public <T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType)
throws RestClientException {
public <T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) {
return this.restTemplate.postForEntity(applyRootUriIfNecessary(url), request, responseType);
}
@ -499,7 +496,7 @@ public class TestRestTemplate {
* @see HttpEntity
* @see RestTemplate#put(java.lang.String, java.lang.Object, java.lang.Object[])
*/
public void put(String url, Object request, Object... urlVariables) throws RestClientException {
public void put(String url, Object request, Object... urlVariables) {
this.restTemplate.put(url, request, urlVariables);
}
@ -519,7 +516,7 @@ public class TestRestTemplate {
* @see HttpEntity
* @see RestTemplate#put(java.lang.String, java.lang.Object, java.util.Map)
*/
public void put(String url, Object request, Map<String, ?> urlVariables) throws RestClientException {
public void put(String url, Object request, Map<String, ?> urlVariables) {
this.restTemplate.put(url, request, urlVariables);
}
@ -536,7 +533,7 @@ public class TestRestTemplate {
* @see HttpEntity
* @see RestTemplate#put(java.net.URI, java.lang.Object)
*/
public void put(URI url, Object request) throws RestClientException {
public void put(URI url, Object request) {
this.restTemplate.put(applyRootUriIfNecessary(url), request);
}
@ -557,8 +554,7 @@ public class TestRestTemplate {
* @since 1.4.4
* @see HttpEntity
*/
public <T> T patchForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException {
public <T> T patchForObject(String url, Object request, Class<T> responseType, Object... uriVariables) {
return this.restTemplate.patchForObject(url, request, responseType, uriVariables);
}
@ -579,8 +575,7 @@ public class TestRestTemplate {
* @since 1.4.4
* @see HttpEntity
*/
public <T> T patchForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException {
public <T> T patchForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) {
return this.restTemplate.patchForObject(url, request, responseType, uriVariables);
}
@ -598,7 +593,7 @@ public class TestRestTemplate {
* @since 1.4.4
* @see HttpEntity
*/
public <T> T patchForObject(URI url, Object request, Class<T> responseType) throws RestClientException {
public <T> T patchForObject(URI url, Object request, Class<T> responseType) {
return this.restTemplate.patchForObject(applyRootUriIfNecessary(url), request, responseType);
}
@ -613,7 +608,7 @@ public class TestRestTemplate {
* @param urlVariables the variables to expand in the template
* @see RestTemplate#delete(java.lang.String, java.lang.Object[])
*/
public void delete(String url, Object... urlVariables) throws RestClientException {
public void delete(String url, Object... urlVariables) {
this.restTemplate.delete(url, urlVariables);
}
@ -628,7 +623,7 @@ public class TestRestTemplate {
* @param urlVariables the variables to expand the template
* @see RestTemplate#delete(java.lang.String, java.util.Map)
*/
public void delete(String url, Map<String, ?> urlVariables) throws RestClientException {
public void delete(String url, Map<String, ?> urlVariables) {
this.restTemplate.delete(url, urlVariables);
}
@ -640,7 +635,7 @@ public class TestRestTemplate {
* @param url the URL
* @see RestTemplate#delete(java.net.URI)
*/
public void delete(URI url) throws RestClientException {
public void delete(URI url) {
this.restTemplate.delete(applyRootUriIfNecessary(url));
}
@ -653,7 +648,7 @@ public class TestRestTemplate {
* @return the value of the allow header
* @see RestTemplate#optionsForAllow(java.lang.String, java.lang.Object[])
*/
public Set<HttpMethod> optionsForAllow(String url, Object... urlVariables) throws RestClientException {
public Set<HttpMethod> optionsForAllow(String url, Object... urlVariables) {
return this.restTemplate.optionsForAllow(url, urlVariables);
}
@ -666,7 +661,7 @@ public class TestRestTemplate {
* @return the value of the allow header
* @see RestTemplate#optionsForAllow(java.lang.String, java.util.Map)
*/
public Set<HttpMethod> optionsForAllow(String url, Map<String, ?> urlVariables) throws RestClientException {
public Set<HttpMethod> optionsForAllow(String url, Map<String, ?> urlVariables) {
return this.restTemplate.optionsForAllow(url, urlVariables);
}
@ -676,7 +671,7 @@ public class TestRestTemplate {
* @return the value of the allow header
* @see RestTemplate#optionsForAllow(java.net.URI)
*/
public Set<HttpMethod> optionsForAllow(URI url) throws RestClientException {
public Set<HttpMethod> optionsForAllow(URI url) {
return this.restTemplate.optionsForAllow(applyRootUriIfNecessary(url));
}
@ -697,7 +692,7 @@ public class TestRestTemplate {
* org.springframework.http.HttpEntity, java.lang.Class, java.lang.Object[])
*/
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType, Object... urlVariables) throws RestClientException {
Class<T> responseType, Object... urlVariables) {
return this.restTemplate.exchange(url, method, requestEntity, responseType, urlVariables);
}
@ -718,7 +713,7 @@ public class TestRestTemplate {
* org.springframework.http.HttpEntity, java.lang.Class, java.util.Map)
*/
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType, Map<String, ?> urlVariables) throws RestClientException {
Class<T> responseType, Map<String, ?> urlVariables) {
return this.restTemplate.exchange(url, method, requestEntity, responseType, urlVariables);
}
@ -736,7 +731,7 @@ public class TestRestTemplate {
* org.springframework.http.HttpEntity, java.lang.Class)
*/
public <T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType) throws RestClientException {
Class<T> responseType) {
return this.restTemplate.exchange(applyRootUriIfNecessary(url), method, requestEntity, responseType);
}
@ -761,7 +756,7 @@ public class TestRestTemplate {
* org.springframework.core.ParameterizedTypeReference, java.lang.Object[])
*/
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType, Object... urlVariables) throws RestClientException {
ParameterizedTypeReference<T> responseType, Object... urlVariables) {
return this.restTemplate.exchange(url, method, requestEntity, responseType, urlVariables);
}
@ -786,7 +781,7 @@ public class TestRestTemplate {
* org.springframework.core.ParameterizedTypeReference, java.util.Map)
*/
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType, Map<String, ?> urlVariables) throws RestClientException {
ParameterizedTypeReference<T> responseType, Map<String, ?> urlVariables) {
return this.restTemplate.exchange(url, method, requestEntity, responseType, urlVariables);
}
@ -810,7 +805,7 @@ public class TestRestTemplate {
* org.springframework.core.ParameterizedTypeReference)
*/
public <T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType) throws RestClientException {
ParameterizedTypeReference<T> responseType) {
return this.restTemplate.exchange(applyRootUriIfNecessary(url), method, requestEntity, responseType);
}
@ -828,8 +823,7 @@ public class TestRestTemplate {
* @return the response as entity
* @see RestTemplate#exchange(org.springframework.http.RequestEntity, java.lang.Class)
*/
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType)
throws RestClientException {
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType) {
return this.restTemplate.exchange(createRequestEntityWithRootAppliedUri(requestEntity), responseType);
}
@ -849,8 +843,7 @@ public class TestRestTemplate {
* @see RestTemplate#exchange(org.springframework.http.RequestEntity,
* org.springframework.core.ParameterizedTypeReference)
*/
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType)
throws RestClientException {
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType) {
return this.restTemplate.exchange(createRequestEntityWithRootAppliedUri(requestEntity), responseType);
}
@ -871,7 +864,7 @@ public class TestRestTemplate {
* org.springframework.web.client.ResponseExtractor, java.lang.Object[])
*/
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, Object... urlVariables) throws RestClientException {
ResponseExtractor<T> responseExtractor, Object... urlVariables) {
return this.restTemplate.execute(url, method, requestCallback, responseExtractor, urlVariables);
}
@ -892,7 +885,7 @@ public class TestRestTemplate {
* org.springframework.web.client.ResponseExtractor, java.util.Map)
*/
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, Map<String, ?> urlVariables) throws RestClientException {
ResponseExtractor<T> responseExtractor, Map<String, ?> urlVariables) {
return this.restTemplate.execute(url, method, requestCallback, responseExtractor, urlVariables);
}
@ -910,7 +903,7 @@ public class TestRestTemplate {
* org.springframework.web.client.ResponseExtractor)
*/
public <T> T execute(URI url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor) throws RestClientException {
ResponseExtractor<T> responseExtractor) {
return this.restTemplate.execute(applyRootUriIfNecessary(url), method, requestCallback, responseExtractor);
}