Browse Source
Introduce separate test classes for each base class in the hierarchy above @ResponseBody and ResponseEntity result handlers. Also start porting existing unit test cases for @ResponseBody and ResponseEntity return value handlers.pull/1111/head
7 changed files with 464 additions and 149 deletions
@ -0,0 +1,137 @@
@@ -0,0 +1,137 @@
|
||||
/* |
||||
* Copyright 2002-2016 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.web.reactive.result; |
||||
|
||||
import java.net.URI; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
import org.springframework.core.convert.support.GenericConversionService; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.http.server.reactive.MockServerHttpRequest; |
||||
import org.springframework.http.server.reactive.MockServerHttpResponse; |
||||
import org.springframework.web.reactive.accept.FixedContentTypeResolver; |
||||
import org.springframework.web.reactive.accept.HeaderContentTypeResolver; |
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange; |
||||
import org.springframework.web.server.session.WebSessionManager; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.springframework.http.MediaType.ALL; |
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8; |
||||
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM; |
||||
import static org.springframework.http.MediaType.IMAGE_GIF; |
||||
import static org.springframework.http.MediaType.IMAGE_JPEG; |
||||
import static org.springframework.http.MediaType.IMAGE_PNG; |
||||
import static org.springframework.http.MediaType.TEXT_PLAIN; |
||||
import static org.springframework.web.reactive.HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE; |
||||
|
||||
/** |
||||
* Unit tests for {@link ContentNegotiatingResultHandlerSupport}. |
||||
* @author Rossen Stoyanchev |
||||
*/ |
||||
public class ContentNegotiatingResultHandlerSupportTests { |
||||
|
||||
private TestHandlerSupport handlerSupport; |
||||
|
||||
private MockServerHttpRequest request; |
||||
|
||||
private ServerWebExchange exchange; |
||||
|
||||
|
||||
@Before |
||||
public void setUp() throws Exception { |
||||
this.handlerSupport = new TestHandlerSupport(); |
||||
this.request = new MockServerHttpRequest(HttpMethod.GET, new URI("/path")); |
||||
this.exchange = new DefaultServerWebExchange( |
||||
this.request, new MockServerHttpResponse(), mock(WebSessionManager.class)); |
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void usesContentTypeResolver() throws Exception { |
||||
RequestedContentTypeResolver resolver = new FixedContentTypeResolver(IMAGE_GIF); |
||||
TestHandlerSupport handlerSupport = new TestHandlerSupport(resolver); |
||||
|
||||
List<MediaType> mediaTypes = Arrays.asList(IMAGE_JPEG, IMAGE_GIF, IMAGE_PNG); |
||||
MediaType actual = handlerSupport.selectMediaType(this.exchange, mediaTypes); |
||||
|
||||
assertEquals(IMAGE_GIF, actual); |
||||
} |
||||
|
||||
@Test |
||||
public void producibleMediaTypesRequestAttribute() throws Exception { |
||||
Set<MediaType> producible = Collections.singleton(IMAGE_GIF); |
||||
this.exchange.getAttributes().put(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, producible); |
||||
|
||||
List<MediaType> mediaTypes = Arrays.asList(IMAGE_JPEG, IMAGE_GIF, IMAGE_PNG); |
||||
MediaType actual = handlerSupport.selectMediaType(this.exchange, mediaTypes); |
||||
|
||||
assertEquals(IMAGE_GIF, actual); |
||||
} |
||||
|
||||
@Test // SPR-9160
|
||||
public void sortsByQuality() throws Exception { |
||||
this.request.getHeaders().add("Accept", "text/plain; q=0.5, application/json"); |
||||
|
||||
List<MediaType> mediaTypes = Arrays.asList(TEXT_PLAIN, APPLICATION_JSON_UTF8); |
||||
MediaType actual = this.handlerSupport.selectMediaType(this.exchange, mediaTypes); |
||||
|
||||
assertEquals(APPLICATION_JSON_UTF8, actual); |
||||
} |
||||
|
||||
@Test |
||||
public void charsetFromAcceptHeader() throws Exception { |
||||
MediaType text8859 = MediaType.parseMediaType("text/plain;charset=ISO-8859-1"); |
||||
MediaType textUtf8 = MediaType.parseMediaType("text/plain;charset=UTF-8"); |
||||
|
||||
this.request.getHeaders().setAccept(Collections.singletonList(text8859)); |
||||
MediaType actual = this.handlerSupport.selectMediaType(this.exchange, Collections.singletonList(textUtf8)); |
||||
|
||||
assertEquals(text8859, actual); |
||||
} |
||||
|
||||
@Test // SPR-12894
|
||||
public void noConcreteMediaType() throws Exception { |
||||
List<MediaType> producible = Collections.singletonList(ALL); |
||||
MediaType actual = this.handlerSupport.selectMediaType(this.exchange, producible); |
||||
|
||||
assertEquals(APPLICATION_OCTET_STREAM, actual); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
private static class TestHandlerSupport extends ContentNegotiatingResultHandlerSupport { |
||||
|
||||
protected TestHandlerSupport() { |
||||
this(new HeaderContentTypeResolver()); |
||||
} |
||||
|
||||
public TestHandlerSupport(RequestedContentTypeResolver contentTypeResolver) { |
||||
super(new GenericConversionService(), contentTypeResolver); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
/* |
||||
* Copyright 2002-2016 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.web.reactive.result.method.annotation; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.OutputStream; |
||||
import java.net.URI; |
||||
import java.nio.charset.Charset; |
||||
import java.time.Duration; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Ignore; |
||||
import org.junit.Test; |
||||
import reactor.core.publisher.Flux; |
||||
import reactor.core.publisher.Mono; |
||||
import reactor.core.test.TestSubscriber; |
||||
import rx.Observable; |
||||
|
||||
import org.springframework.core.ResolvableType; |
||||
import org.springframework.core.codec.Decoder; |
||||
import org.springframework.core.codec.Encoder; |
||||
import org.springframework.core.codec.support.ByteBufferDecoder; |
||||
import org.springframework.core.codec.support.ByteBufferEncoder; |
||||
import org.springframework.core.codec.support.JacksonJsonDecoder; |
||||
import org.springframework.core.codec.support.JacksonJsonEncoder; |
||||
import org.springframework.core.codec.support.Jaxb2Decoder; |
||||
import org.springframework.core.codec.support.Jaxb2Encoder; |
||||
import org.springframework.core.codec.support.JsonObjectDecoder; |
||||
import org.springframework.core.codec.support.StringDecoder; |
||||
import org.springframework.core.codec.support.StringEncoder; |
||||
import org.springframework.core.convert.support.GenericConversionService; |
||||
import org.springframework.core.convert.support.ReactiveStreamsToCompletableFutureConverter; |
||||
import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter; |
||||
import org.springframework.core.io.ByteArrayResource; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.core.io.buffer.support.DataBufferTestUtils; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.converter.reactive.CodecHttpMessageConverter; |
||||
import org.springframework.http.converter.reactive.HttpMessageConverter; |
||||
import org.springframework.http.converter.reactive.ResourceHttpMessageConverter; |
||||
import org.springframework.http.server.reactive.MockServerHttpRequest; |
||||
import org.springframework.http.server.reactive.MockServerHttpResponse; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.util.ObjectUtils; |
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver; |
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange; |
||||
import org.springframework.web.server.session.WebSessionManager; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNull; |
||||
import static org.mockito.Mockito.mock; |
||||
|
||||
/** |
||||
* Unit tests for {@link AbstractMessageConverterResultHandler}. |
||||
* @author Rossen Stoyanchev |
||||
*/ |
||||
public class MessageConverterResultHandlerTests { |
||||
|
||||
private AbstractMessageConverterResultHandler resultHandler; |
||||
|
||||
private MockServerHttpResponse response = new MockServerHttpResponse(); |
||||
|
||||
private ServerWebExchange exchange; |
||||
|
||||
|
||||
@Before |
||||
public void setUp() throws Exception { |
||||
this.resultHandler = createResultHandler(); |
||||
ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, new URI("/path")); |
||||
this.exchange = new DefaultServerWebExchange(request, this.response, mock(WebSessionManager.class)); |
||||
} |
||||
|
||||
|
||||
@Test // SPR-12894
|
||||
@Ignore // GH # 121
|
||||
public void useDefaultContentType() throws Exception { |
||||
Object body = new ByteArrayResource("body".getBytes("UTF-8")); |
||||
ResolvableType bodyType = ResolvableType.forType(Resource.class); |
||||
this.resultHandler.writeBody(this.exchange, body, bodyType).block(Duration.ofSeconds(5)); |
||||
|
||||
assertEquals("image/jpeg", this.response.getHeaders().getFirst("Content-Type")); |
||||
TestSubscriber.subscribe(this.response.getBody()) |
||||
.assertValuesWith(buf -> assertEquals("body", |
||||
DataBufferTestUtils.dumpString(buf, Charset.forName("UTF-8")))); |
||||
} |
||||
|
||||
@Test |
||||
public void voidReturnType() throws Exception { |
||||
testVoidReturnType(null, ResolvableType.forType(Void.class)); |
||||
testVoidReturnType(Mono.empty(), ResolvableType.forClassWithGenerics(Mono.class, Void.class)); |
||||
testVoidReturnType(Flux.empty(), ResolvableType.forClassWithGenerics(Flux.class, Void.class)); |
||||
testVoidReturnType(Observable.empty(), ResolvableType.forClassWithGenerics(Observable.class, Void.class)); |
||||
} |
||||
|
||||
private void testVoidReturnType(Object body, ResolvableType bodyType) { |
||||
this.resultHandler.writeBody(this.exchange, body, bodyType).block(Duration.ofSeconds(5)); |
||||
|
||||
assertNull(this.response.getHeaders().get("Content-Type")); |
||||
assertNull(this.response.getBody()); |
||||
} |
||||
|
||||
@Test // SPR-13135
|
||||
public void unsupportedReturnType() throws Exception { |
||||
ByteArrayOutputStream body = new ByteArrayOutputStream(); |
||||
ResolvableType bodyType = ResolvableType.forType(OutputStream.class); |
||||
|
||||
HttpMessageConverter<?> converter = new CodecHttpMessageConverter<>(new ByteBufferEncoder()); |
||||
Mono<Void> mono = createResultHandler(converter).writeBody(this.exchange, body, bodyType); |
||||
|
||||
TestSubscriber.subscribe(mono).assertError(IllegalStateException.class); |
||||
} |
||||
|
||||
|
||||
private AbstractMessageConverterResultHandler createResultHandler(HttpMessageConverter<?>... converters) { |
||||
List<HttpMessageConverter<?>> converterList; |
||||
if (ObjectUtils.isEmpty(converters)) { |
||||
converterList = new ArrayList<>(); |
||||
converterList.add(new CodecHttpMessageConverter<>(new ByteBufferEncoder())); |
||||
converterList.add(new CodecHttpMessageConverter<>(new StringEncoder())); |
||||
converterList.add(new ResourceHttpMessageConverter()); |
||||
converterList.add(new CodecHttpMessageConverter<>(new Jaxb2Encoder())); |
||||
converterList.add(new CodecHttpMessageConverter<>(new JacksonJsonEncoder())); |
||||
} |
||||
else { |
||||
converterList = Arrays.asList(converters); |
||||
} |
||||
|
||||
GenericConversionService service = new GenericConversionService(); |
||||
service.addConverter(new ReactiveStreamsToCompletableFutureConverter()); |
||||
service.addConverter(new ReactiveStreamsToRxJava1Converter()); |
||||
|
||||
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build(); |
||||
|
||||
return new AbstractMessageConverterResultHandler(converterList, service, resolver) {}; |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue