@ -19,7 +19,7 @@ package org.springframework.web.client;
import java.io.ByteArrayInputStream ;
import java.io.ByteArrayInputStream ;
import java.io.IOException ;
import java.io.IOException ;
import java.lang.reflect.Type ;
import java.lang.reflect.Type ;
import java.util.ArrayLi st ;
import java.util.Arrays ;
import java.util.List ;
import java.util.List ;
import org.junit.Test ;
import org.junit.Test ;
@ -34,8 +34,10 @@ import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter ;
import org.springframework.http.converter.HttpMessageConverter ;
import org.springframework.http.converter.HttpMessageNotReadableException ;
import org.springframework.http.converter.HttpMessageNotReadableException ;
import static java.util.Arrays.asList ;
import static org.assertj.core.api.Assertions.assertThat ;
import static org.assertj.core.api.Assertions.assertThat ;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType ;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType ;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException ;
import static org.mockito.ArgumentMatchers.any ;
import static org.mockito.ArgumentMatchers.any ;
import static org.mockito.ArgumentMatchers.eq ;
import static org.mockito.ArgumentMatchers.eq ;
import static org.mockito.BDDMockito.given ;
import static org.mockito.BDDMockito.given ;
@ -46,18 +48,30 @@ import static org.mockito.Mockito.mock;
*
*
* @author Arjen Poutsma
* @author Arjen Poutsma
* @author Brian Clozel
* @author Brian Clozel
* @author Sam Brannen
* /
* /
public class HttpMessageConverterExtractorTests {
public class HttpMessageConverterExtractorTests {
private HttpMessageConverterExtractor < ? > extractor ;
@SuppressWarnings ( "unchecked" )
private final HttpMessageConverter < String > converter = mock ( HttpMessageConverter . class ) ;
private final HttpMessageConverterExtractor < ? > extractor = new HttpMessageConverterExtractor < > ( String . class , asList ( converter ) ) ;
private final MediaType contentType = MediaType . TEXT_PLAIN ;
private final HttpHeaders responseHeaders = new HttpHeaders ( ) ;
private final ClientHttpResponse response = mock ( ClientHttpResponse . class ) ;
private final ClientHttpResponse response = mock ( ClientHttpResponse . class ) ;
@Test
public void constructorPreconditions ( ) {
assertThatIllegalArgumentException ( )
. isThrownBy ( ( ) - > new HttpMessageConverterExtractor < > ( String . class , ( List < HttpMessageConverter < ? > > ) null ) )
. withMessage ( "'messageConverters' must not be empty" ) ;
assertThatIllegalArgumentException ( )
. isThrownBy ( ( ) - > new HttpMessageConverterExtractor < > ( String . class , Arrays . asList ( null , this . converter ) ) )
. withMessage ( "'messageConverters' must not contain null elements" ) ;
}
@Test
@Test
public void noContent ( ) throws IOException {
public void noContent ( ) throws IOException {
HttpMessageConverter < ? > converter = mock ( HttpMessageConverter . class ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . NO_CONTENT . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . NO_CONTENT . value ( ) ) ;
Object result = extractor . extractData ( response ) ;
Object result = extractor . extractData ( response ) ;
@ -66,8 +80,6 @@ public class HttpMessageConverterExtractorTests {
@Test
@Test
public void notModified ( ) throws IOException {
public void notModified ( ) throws IOException {
HttpMessageConverter < ? > converter = mock ( HttpMessageConverter . class ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . NOT_MODIFIED . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . NOT_MODIFIED . value ( ) ) ;
Object result = extractor . extractData ( response ) ;
Object result = extractor . extractData ( response ) ;
@ -76,8 +88,6 @@ public class HttpMessageConverterExtractorTests {
@Test
@Test
public void informational ( ) throws IOException {
public void informational ( ) throws IOException {
HttpMessageConverter < ? > converter = mock ( HttpMessageConverter . class ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . CONTINUE . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . CONTINUE . value ( ) ) ;
Object result = extractor . extractData ( response ) ;
Object result = extractor . extractData ( response ) ;
@ -86,10 +96,7 @@ public class HttpMessageConverterExtractorTests {
@Test
@Test
public void zeroContentLength ( ) throws IOException {
public void zeroContentLength ( ) throws IOException {
HttpMessageConverter < ? > converter = mock ( HttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
responseHeaders . setContentLength ( 0 ) ;
responseHeaders . setContentLength ( 0 ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
@ -98,11 +105,7 @@ public class HttpMessageConverterExtractorTests {
}
}
@Test
@Test
@SuppressWarnings ( "unchecked" )
public void emptyMessageBody ( ) throws IOException {
public void emptyMessageBody ( ) throws IOException {
HttpMessageConverter < String > converter = mock ( HttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "" . getBytes ( ) ) ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "" . getBytes ( ) ) ) ;
@ -112,11 +115,7 @@ public class HttpMessageConverterExtractorTests {
}
}
@Test // gh-22265
@Test // gh-22265
@SuppressWarnings ( "unchecked" )
public void nullMessageBody ( ) throws IOException {
public void nullMessageBody ( ) throws IOException {
HttpMessageConverter < String > converter = mock ( HttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getBody ( ) ) . willReturn ( null ) ;
given ( response . getBody ( ) ) . willReturn ( null ) ;
@ -126,14 +125,9 @@ public class HttpMessageConverterExtractorTests {
}
}
@Test
@Test
@SuppressWarnings ( "unchecked" )
public void normal ( ) throws IOException {
public void normal ( ) throws IOException {
HttpMessageConverter < String > converter = mock ( HttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
MediaType contentType = MediaType . TEXT_PLAIN ;
responseHeaders . setContentType ( contentType ) ;
responseHeaders . setContentType ( contentType ) ;
String expected = "Foo" ;
String expected = "Foo" ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( expected . getBytes ( ) ) ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( expected . getBytes ( ) ) ) ;
@ -145,32 +139,26 @@ public class HttpMessageConverterExtractorTests {
}
}
@Test
@Test
@SuppressWarnings ( "unchecked" )
public void cannotRead ( ) throws IOException {
public void cannotRead ( ) throws IOException {
HttpMessageConverter < String > converter = mock ( HttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
MediaType contentType = MediaType . TEXT_PLAIN ;
responseHeaders . setContentType ( contentType ) ;
responseHeaders . setContentType ( contentType ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "Foobar" . getBytes ( ) ) ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "Foobar" . getBytes ( ) ) ) ;
given ( converter . canRead ( String . class , contentType ) ) . willReturn ( false ) ;
given ( converter . canRead ( String . class , contentType ) ) . willReturn ( false ) ;
assertThatExceptionOfType ( RestClientException . class ) . isThrownBy ( ( ) - >
assertThatExceptionOfType ( RestClientException . class ) . isThrownBy ( ( ) - > extractor . extractData ( response ) ) ;
extractor . extractData ( response ) ) ;
}
}
@Test
@Test
@SuppressWarnings ( "unchecked" )
@SuppressWarnings ( "unchecked" )
public void generics ( ) throws IOException {
public void generics ( ) throws IOException {
GenericHttpMessageConverter < String > converter = mock ( GenericHttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
MediaType contentType = MediaType . TEXT_PLAIN ;
responseHeaders . setContentType ( contentType ) ;
responseHeaders . setContentType ( contentType ) ;
String expected = "Foo" ;
String expected = "Foo" ;
ParameterizedTypeReference < List < String > > reference = new ParameterizedTypeReference < List < String > > ( ) { } ;
ParameterizedTypeReference < List < String > > reference = new ParameterizedTypeReference < List < String > > ( ) { } ;
Type type = reference . getType ( ) ;
Type type = reference . getType ( ) ;
extractor = new HttpMessageConverterExtractor < List < String > > ( type , createConverterList ( converter ) ) ;
GenericHttpMessageConverter < String > converter = mock ( GenericHttpMessageConverter . class ) ;
HttpMessageConverterExtractor < ? > extractor = new HttpMessageConverterExtractor < List < String > > ( type , asList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( expected . getBytes ( ) ) ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( expected . getBytes ( ) ) ) ;
@ -182,48 +170,28 @@ public class HttpMessageConverterExtractorTests {
}
}
@Test // SPR-13592
@Test // SPR-13592
@SuppressWarnings ( "unchecked" )
public void converterThrowsIOException ( ) throws IOException {
public void converterThrowsIOException ( ) throws IOException {
HttpMessageConverter < String > converter = mock ( HttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
MediaType contentType = MediaType . TEXT_PLAIN ;
responseHeaders . setContentType ( contentType ) ;
responseHeaders . setContentType ( contentType ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "Foobar" . getBytes ( ) ) ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "Foobar" . getBytes ( ) ) ) ;
given ( converter . canRead ( String . class , contentType ) ) . willReturn ( true ) ;
given ( converter . canRead ( String . class , contentType ) ) . willReturn ( true ) ;
given ( converter . read ( eq ( String . class ) , any ( HttpInputMessage . class ) ) ) . willThrow ( IOException . class ) ;
given ( converter . read ( eq ( String . class ) , any ( HttpInputMessage . class ) ) ) . willThrow ( IOException . class ) ;
assertThatExceptionOfType ( RestClientException . class ) . isThrownBy ( ( ) - >
assertThatExceptionOfType ( RestClientException . class ) . isThrownBy ( ( ) - > extractor . extractData ( response ) )
extractor . extractData ( response ) )
. withMessageContaining ( "Error while extracting response for type [class java.lang.String] and content type [text/plain]" )
. withMessageContaining ( "Error while extracting response for type [class java.lang.String] and content type [text/plain]" )
. withCauseInstanceOf ( IOException . class ) ;
. withCauseInstanceOf ( IOException . class ) ;
}
}
@Test // SPR-13592
@Test // SPR-13592
@SuppressWarnings ( "unchecked" )
public void converterThrowsHttpMessageNotReadableException ( ) throws IOException {
public void converterThrowsHttpMessageNotReadableException ( ) throws IOException {
HttpMessageConverter < String > converter = mock ( HttpMessageConverter . class ) ;
HttpHeaders responseHeaders = new HttpHeaders ( ) ;
MediaType contentType = MediaType . TEXT_PLAIN ;
responseHeaders . setContentType ( contentType ) ;
responseHeaders . setContentType ( contentType ) ;
extractor = new HttpMessageConverterExtractor < > ( String . class , createConverterList ( converter ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getRawStatusCode ( ) ) . willReturn ( HttpStatus . OK . value ( ) ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getHeaders ( ) ) . willReturn ( responseHeaders ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "Foobar" . getBytes ( ) ) ) ;
given ( response . getBody ( ) ) . willReturn ( new ByteArrayInputStream ( "Foobar" . getBytes ( ) ) ) ;
given ( converter . canRead ( String . class , contentType ) ) . willThrow ( HttpMessageNotReadableException . class ) ;
given ( converter . canRead ( String . class , contentType ) ) . willThrow ( HttpMessageNotReadableException . class ) ;
assertThatExceptionOfType ( RestClientException . class ) . isThrownBy ( ( ) - >
assertThatExceptionOfType ( RestClientException . class ) . isThrownBy ( ( ) - > extractor . extractData ( response ) )
extractor . extractData ( response ) )
. withMessageContaining ( "Error while extracting response for type [class java.lang.String] and content type [text/plain]" )
. withMessageContaining ( "Error while extracting response for type [class java.lang.String] and content type [text/plain]" )
. withCauseInstanceOf ( HttpMessageNotReadableException . class ) ;
. withCauseInstanceOf ( HttpMessageNotReadableException . class ) ;
}
private List < HttpMessageConverter < ? > > createConverterList ( HttpMessageConverter < ? > converter ) {
List < HttpMessageConverter < ? > > converters = new ArrayList < > ( 1 ) ;
converters . add ( converter ) ;
return converters ;
}
}
}
}