This commit is contained in:
Rossen Stoyanchev 2017-04-20 07:45:19 -04:00
parent 62584a5337
commit 633544943f
1 changed files with 59 additions and 62 deletions

View File

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