From 9cc01fc185a70f56acd5adb5355ae09a44d614a7 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 6 Jul 2016 14:10:51 -0400 Subject: [PATCH] Add @RequestBody tests --- .../RequestBodyArgumentResolver.java | 6 +- .../RequestBodyArgumentResolverTests.java | 82 ++++++++++++++++++- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java index 9113e3f24e..d99240b436 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java @@ -124,15 +124,13 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve } @Override - public Mono resolveArgument(MethodParameter parameter, ModelMap model, - ServerWebExchange exchange) { - - ResolvableType type = ResolvableType.forMethodParameter(parameter); + public Mono resolveArgument(MethodParameter parameter, ModelMap model, ServerWebExchange exchange) { TypeDescriptor typeDescriptor = new TypeDescriptor(parameter); boolean convertFromMono = getConversionService().canConvert(MONO_TYPE, typeDescriptor); boolean convertFromFlux = getConversionService().canConvert(FLUX_TYPE, typeDescriptor); + ResolvableType type = ResolvableType.forMethodParameter(parameter); ResolvableType elementType = convertFromMono || convertFromFlux ? type.getGeneric(0) : type; ServerHttpRequest request = exchange.getRequest(); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java index 0c8e36d6f8..471f11dbd8 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java @@ -15,6 +15,8 @@ */ package org.springframework.web.reactive.result.method.annotation; +import java.io.Serializable; +import java.lang.reflect.Method; import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.Charset; @@ -29,6 +31,7 @@ import java.util.concurrent.CompletableFuture; import javax.xml.bind.annotation.XmlRootElement; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -120,6 +123,17 @@ public class RequestBodyArgumentResolverTests { .assertError(UnsupportedMediaTypeStatusException.class); } + @Test // SPR-9942 + public void missingContent() throws Exception { + this.request.writeWith(Flux.empty()); + ResolvableType type = forClassWithGenerics(Mono.class, TestBean.class); + MethodParameter param = this.testMethod.resolveParam(type); + Mono result = this.resolver.resolveArgument(param, new ExtendedModelMap(), this.exchange); + + TestSubscriber.subscribe(result) + .assertError(UnsupportedMediaTypeStatusException.class); + } + @Test @SuppressWarnings("unchecked") public void monoTestBean() throws Exception { String body = "{\"bar\":\"b1\",\"foo\":\"f1\"}"; @@ -205,6 +219,17 @@ public class RequestBodyArgumentResolverTests { assertEquals(Arrays.asList(new TestBean("f1", "b1"), new TestBean("f2", "b2")), list); } + @Test + public void monoList() throws Exception { + String body = "[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]"; + ResolvableType type = forClassWithGenerics(Mono.class, forClassWithGenerics(List.class, TestBean.class)); + MethodParameter param = this.testMethod.resolveParam(type); + Mono mono = resolveValue(param, Mono.class, body); + + List list = (List) mono.block(Duration.ofSeconds(5)); + assertEquals(Arrays.asList(new TestBean("f1", "b1"), new TestBean("f2", "b2")), list); + } + @Test public void array() throws Exception { String body = "[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]"; @@ -239,6 +264,17 @@ public class RequestBodyArgumentResolverTests { .assertError(ServerWebInputException.class); } + @Test // SPR-9964 + @Ignore + public void parameterizedMethodArgument() throws Exception { + Class clazz = ConcreteParameterizedController.class; + MethodParameter param = ResolvableMethod.on(clazz).name("handleDto").resolveParam(); + SimpleBean simpleBean = resolveValue(param, SimpleBean.class, "{\"name\" : \"Jad\"}"); + + assertEquals("Jad", simpleBean.getName()); + } + + @SuppressWarnings("unchecked") private T resolveValue(MethodParameter param, Class valueType, String body) { @@ -250,7 +286,7 @@ public class RequestBodyArgumentResolverTests { Object value = result.block(Duration.ofSeconds(5)); assertNotNull(value); - assertTrue("Actual type: " + value.getClass(), valueType.isAssignableFrom(value.getClass())); + assertTrue("Unexpected return value type: " + value, valueType.isAssignableFrom(value.getClass())); return (T) value; } @@ -285,6 +321,7 @@ public class RequestBodyArgumentResolverTests { @RequestBody TestBean testBean, @RequestBody Map map, @RequestBody List list, + @RequestBody Mono> monoList, @RequestBody Set set, @RequestBody TestBean[] array, TestBean paramWithoutAnnotation) { @@ -361,4 +398,47 @@ public class RequestBodyArgumentResolverTests { } } } + + private static abstract class AbstractParameterizedController { + + @SuppressWarnings("unused") + public void handleDto(@RequestBody DTO dto) {} + } + + private static class ConcreteParameterizedController extends AbstractParameterizedController { + } + + private interface Identifiable extends Serializable { + + Long getId(); + + void setId(Long id); + } + + @SuppressWarnings({ "serial" }) + private static class SimpleBean implements Identifiable { + + private Long id; + + private String name; + + @Override + public Long getId() { + return id; + } + + @Override + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + }