@ -15,7 +15,6 @@
@@ -15,7 +15,6 @@
* /
package org.springframework.web.servlet.mvc.method.annotation ;
import java.lang.reflect.Method ;
import java.util.Arrays ;
import java.util.Collections ;
import java.util.List ;
@ -25,9 +24,6 @@ import org.junit.Before;
@@ -25,9 +24,6 @@ import org.junit.Before;
import org.junit.Test ;
import org.springframework.core.MethodParameter ;
import org.springframework.core.ReactiveAdapterRegistry ;
import org.springframework.core.task.SyncTaskExecutor ;
import org.springframework.core.task.TaskExecutor ;
import org.springframework.http.ResponseEntity ;
import org.springframework.http.converter.HttpMessageConverter ;
import org.springframework.http.converter.StringHttpMessageConverter ;
@ -35,7 +31,6 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
@@ -35,7 +31,6 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
import org.springframework.mock.web.test.MockAsyncContext ;
import org.springframework.mock.web.test.MockHttpServletRequest ;
import org.springframework.mock.web.test.MockHttpServletResponse ;
import org.springframework.web.accept.ContentNegotiationManager ;
import org.springframework.web.context.request.NativeWebRequest ;
import org.springframework.web.context.request.ServletWebRequest ;
import org.springframework.web.context.request.async.AsyncWebRequest ;
@ -43,12 +38,20 @@ import org.springframework.web.context.request.async.StandardServletAsyncWebRequ
@@ -43,12 +38,20 @@ import org.springframework.web.context.request.async.StandardServletAsyncWebRequ
import org.springframework.web.context.request.async.WebAsyncUtils ;
import org.springframework.web.method.support.ModelAndViewContainer ;
import static org.junit.Assert.* ;
import static org.mockito.Mockito.* ;
import static org.junit.Assert.assertEquals ;
import static org.junit.Assert.assertFalse ;
import static org.junit.Assert.assertNotNull ;
import static org.junit.Assert.assertNull ;
import static org.junit.Assert.assertTrue ;
import static org.mockito.Mockito.any ;
import static org.mockito.Mockito.mock ;
import static org.mockito.Mockito.times ;
import static org.mockito.Mockito.verify ;
import static org.springframework.core.ResolvableType.forClassWithGenerics ;
import static org.springframework.web.method.ResolvableMethod.on ;
/ * *
* Unit tests for ResponseBodyEmitterReturnValueHandler .
*
* @author Rossen Stoyanchev
* /
public class ResponseBodyEmitterReturnValueHandlerTests {
@ -61,9 +64,12 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -61,9 +64,12 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
private NativeWebRequest webRequest ;
private final ModelAndViewContainer mavContainer = new ModelAndViewContainer ( ) ;
@Before
public void setup ( ) throws Exception {
List < HttpMessageConverter < ? > > converters = Arrays . asList (
new StringHttpMessageConverter ( ) , new MappingJackson2HttpMessageConverter ( ) ) ;
@ -79,20 +85,37 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -79,20 +85,37 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@Test
public void supportsReturnType ( ) throws Exception {
assertTrue ( this . handler . supportsReturnType ( returnType ( "handle" ) ) ) ;
assertTrue ( this . handler . supportsReturnType ( returnType ( "handleSse" ) ) ) ;
assertTrue ( this . handler . supportsReturnType ( returnType ( "handleResponseEntity" ) ) ) ;
assertFalse ( this . handler . supportsReturnType ( returnType ( "handleResponseEntityString" ) ) ) ;
assertFalse ( this . handler . supportsReturnType ( returnType ( "handleResponseEntityParameterized" ) ) ) ;
assertFalse ( this . handler . supportsReturnType ( returnType ( "handleRawResponseEntity" ) ) ) ;
public void supportsReturnTypes ( ) throws Exception {
assertTrue ( this . handler . supportsReturnType (
on ( TestController . class ) . resolveReturnType ( ResponseBodyEmitter . class ) ) ) ;
assertTrue ( this . handler . supportsReturnType (
on ( TestController . class ) . resolveReturnType ( SseEmitter . class ) ) ) ;
assertTrue ( this . handler . supportsReturnType (
on ( TestController . class ) . resolveReturnType ( ResponseEntity . class , ResponseBodyEmitter . class ) ) ) ;
}
@Test
public void doesNotSupportReturnTypes ( ) throws Exception {
assertFalse ( this . handler . supportsReturnType (
on ( TestController . class ) . resolveReturnType ( ResponseEntity . class , String . class ) ) ) ;
assertFalse ( this . handler . supportsReturnType ( on ( TestController . class )
. resolveReturnType ( forClassWithGenerics ( ResponseEntity . class ,
forClassWithGenerics ( AtomicReference . class , String . class ) ) ) ) ) ;
assertFalse ( this . handler . supportsReturnType (
on ( TestController . class ) . resolveReturnType ( ResponseEntity . class ) ) ) ;
}
@Test
public void responseBodyEmitter ( ) throws Exception {
MethodParameter returnType = returnType ( "handle" ) ;
MethodParameter type = on ( TestController . class ) . resolveReturnType ( ResponseBodyEmitter . class ) ;
ResponseBodyEmitter emitter = new ResponseBodyEmitter ( ) ;
handleReturnValue ( emitter , returnType ) ;
this . handler . handleReturnValue ( emitter , type , this . mavContainer , this . webRequest ) ;
assertTrue ( this . request . isAsyncStarted ( ) ) ;
assertEquals ( "" , this . response . getContentAsString ( ) ) ;
@ -114,8 +137,7 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -114,8 +137,7 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
assertEquals ( "{\"id\":1,\"name\":\"Joe\"}\n" +
"{\"id\":2,\"name\":\"John\"}\n" +
"{\"id\":3,\"name\":\"Jason\"}" ,
this . response . getContentAsString ( ) ) ;
"{\"id\":3,\"name\":\"Jason\"}" , this . response . getContentAsString ( ) ) ;
MockAsyncContext asyncContext = ( MockAsyncContext ) this . request . getAsyncContext ( ) ;
assertNull ( asyncContext . getDispatchedPath ( ) ) ;
@ -125,7 +147,7 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -125,7 +147,7 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
}
@Test
public void timeoutValueAndCallback ( ) throws Exception {
public void responseBodyEmi tterWithT imeoutValue( ) throws Exception {
AsyncWebRequest asyncWebRequest = mock ( AsyncWebRequest . class ) ;
WebAsyncUtils . getAsyncManager ( this . request ) . setAsyncWebRequest ( asyncWebRequest ) ;
@ -134,8 +156,8 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -134,8 +156,8 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
emitter . onTimeout ( mock ( Runnable . class ) ) ;
emitter . onCompletion ( mock ( Runnable . class ) ) ;
MethodParameter returnType = returnType ( "handle" ) ;
handleReturnValue ( emitter , returnType ) ;
MethodParameter type = on ( TestController . class ) . resolveReturnType ( ResponseBodyEmitter . class ) ;
this . handler . handleReturnValue ( emitter , type , this . mavContainer , this . webRequest ) ;
verify ( asyncWebRequest ) . setTimeout ( 19000L ) ;
verify ( asyncWebRequest ) . addTimeoutHandler ( any ( Runnable . class ) ) ;
@ -145,9 +167,9 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -145,9 +167,9 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@Test
public void sseEmitter ( ) throws Exception {
MethodParameter returnType = returnType ( "handleSse" ) ;
MethodParameter type = on ( TestController . class ) . resolveReturnType ( SseEmitter . class ) ;
SseEmitter emitter = new SseEmitter ( ) ;
handleReturnValue ( emitter , returnType ) ;
this . handler . handleReturnValue ( emitter , type , this . mavContainer , this . webRequest ) ;
assertTrue ( this . request . isAsyncStarted ( ) ) ;
assertEquals ( 200 , this . response . getStatus ( ) ) ;
@ -170,15 +192,14 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -170,15 +192,14 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
"retry:5000\n" +
"data:{\"id\":1,\"name\":\"Joe\"}\n" +
"data:{\"id\":2,\"name\":\"John\"}\n" +
"\n" ,
this . response . getContentAsString ( ) ) ;
"\n" , this . response . getContentAsString ( ) ) ;
}
@Test
public void responseEntitySse ( ) throws Exception {
MethodParameter re turnT ype = returnType ( "handleResponseEntitySse" ) ;
MethodParameter type = on ( TestCont roller . class ) . resolveR eturnType( ResponseEntity . class , SseEmitter . class ) ;
ResponseEntity < SseEmitter > entity = ResponseEntity . ok ( ) . header ( "foo" , "bar" ) . body ( new SseEmitter ( ) ) ;
handleReturnValue ( entity , returnType ) ;
this . handler . handleReturnValue ( entity , type , this . mavContainer , this . webRequest ) ;
assertTrue ( this . request . isAsyncStarted ( ) ) ;
assertEquals ( 200 , this . response . getStatus ( ) ) ;
@ -188,9 +209,9 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -188,9 +209,9 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@Test
public void responseEntitySseNoContent ( ) throws Exception {
MethodParameter re turnT ype = returnType ( "handleResponseEntitySse" ) ;
MethodParameter type = on ( TestCont roller . class ) . resolveR eturnType( ResponseEntity . class , SseEmitter . class ) ;
ResponseEntity < ? > entity = ResponseEntity . noContent ( ) . header ( "foo" , "bar" ) . build ( ) ;
handleReturnValue ( entity , returnType ) ;
this . handler . handleReturnValue ( entity , type , this . mavContainer , this . webRequest ) ;
assertFalse ( this . request . isAsyncStarted ( ) ) ;
assertEquals ( 204 , this . response . getStatus ( ) ) ;
@ -198,47 +219,23 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@@ -198,47 +219,23 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
}
private void handleReturnValue ( Object returnValue , MethodParameter returnType ) throws Exception {
ModelAndViewContainer mavContainer = new ModelAndViewContainer ( ) ;
this . handler . handleReturnValue ( returnValue , returnType , mavContainer , this . webRequest ) ;
}
private MethodParameter returnType ( String methodName ) throws NoSuchMethodException {
Method method = TestController . class . getDeclaredMethod ( methodName ) ;
return new MethodParameter ( method , - 1 ) ;
}
@SuppressWarnings ( "unused" )
private static class TestController {
private ResponseBodyEmitter handle ( ) {
return null ;
}
private ResponseBodyEmitter h1 ( ) { return null ; }
private ResponseEntity < ResponseBodyEmitter > handleResponseEntity ( ) {
return null ;
}
private ResponseEntity < ResponseBodyEmitter > h2 ( ) { return null ; }
private SseEmitter handleSse ( ) {
return null ;
}
private SseEmitter h3 ( ) { return null ; }
private ResponseEntity < SseEmitter > handleResponseEntitySse ( ) {
return null ;
}
private ResponseEntity < SseEmitter > h4 ( ) { return null ; }
private ResponseEntity < String > handleResponseEntityString ( ) {
return null ;
}
private ResponseEntity < String > h5 ( ) { return null ; }
private ResponseEntity < AtomicReference < String > > handleResponseEntityParameterized ( ) {
return null ;
}
private ResponseEntity < AtomicReference < String > > h6 ( ) { return null ; }
private ResponseEntity h7 ( ) { return null ; }
private ResponseEntity handleRawResponseEntity ( ) {
return null ;
}
}