Browse Source

@RequestParam tests use ResolvableMethod

pull/1349/merge
Rossen Stoyanchev 9 years ago
parent
commit
cdf19d1db1
  1. 27
      spring-web/src/test/java/org/springframework/web/method/ResolvableMethod.java
  2. 56
      spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMapMethodArgumentResolverTests.java
  3. 287
      spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
  4. 54
      spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolverTests.java
  5. 128
      spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java

27
spring-web/src/test/java/org/springframework/web/method/ResolvableMethod.java

@ -42,7 +42,7 @@ import org.springframework.core.MethodIntrospector;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.objenesis.ObjenesisException; import org.springframework.objenesis.ObjenesisException;
import org.springframework.objenesis.SpringObjenesis; import org.springframework.objenesis.SpringObjenesis;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -83,7 +83,7 @@ import org.springframework.util.ReflectionUtils;
* on(TestController.class).annotated(ResponseBody.class).resolveReturnType(Bar.class); * on(TestController.class).annotated(ResponseBody.class).resolveReturnType(Bar.class);
* *
* // Annotation not present * // Annotation not present
* on(TestController.class).isNotAnnotated(ResponseBody.class).resolveReturnType(); * on(TestController.class).notAnnotated(ResponseBody.class).resolveReturnType();
* *
* // Annotation properties * // Annotation properties
* on(TestController.class) * on(TestController.class)
@ -145,7 +145,7 @@ public class ResolvableMethod {
* Return the declared return type of the resolved method. * Return the declared return type of the resolved method.
*/ */
public MethodParameter returnType() { public MethodParameter returnType() {
return new MethodParameter(this.method, -1); return new SynthesizingMethodParameter(this.method, -1);
} }
/** /**
@ -262,9 +262,17 @@ public class ResolvableMethod {
/** /**
* Filter on methods not annotated with the given annotation type. * Filter on methods not annotated with the given annotation type.
*/ */
public final <A extends Annotation> Builder isNotAnnotated(Class<A> annotationType) { public final Builder notAnnotated(Class<? extends Annotation>... annotationTypes) {
String message = "notAnnotated=" + annotationType.getName(); String message = "notAnnotated=" + Arrays.toString(annotationTypes);
addFilter(message, m -> AnnotationUtils.findAnnotation(m, annotationType) == null); addFilter(message, method -> {
if (annotationTypes.length != 0) {
return Arrays.stream(annotationTypes).noneMatch(annotType ->
AnnotatedElementUtils.findMergedAnnotation(method, annotType) != null);
}
else {
return method.getAnnotations().length == 0;
}
});
return this; return this;
} }
@ -505,7 +513,10 @@ public class ResolvableMethod {
*/ */
@SafeVarargs @SafeVarargs
public final ArgResolver notAnnotated(Class<? extends Annotation>... annotationTypes) { public final ArgResolver notAnnotated(Class<? extends Annotation>... annotationTypes) {
this.filters.add(p -> Arrays.stream(annotationTypes).noneMatch(p::hasParameterAnnotation)); this.filters.add(param ->
(annotationTypes.length != 0) ?
Arrays.stream(annotationTypes).noneMatch(param::hasParameterAnnotation) :
param.getParameterAnnotations().length == 0);
return this; return this;
} }
@ -550,7 +561,7 @@ public class ResolvableMethod {
private List<MethodParameter> applyFilters() { private List<MethodParameter> applyFilters() {
List<MethodParameter> matches = new ArrayList<>(); List<MethodParameter> matches = new ArrayList<>();
for (int i = 0; i < method.getParameterCount(); i++) { for (int i = 0; i < method.getParameterCount(); i++) {
MethodParameter param = new MethodParameter(method, i); MethodParameter param = new SynthesizingMethodParameter(method, i);
if (this.filters.stream().allMatch(p -> p.test(param))) { if (this.filters.stream().allMatch(p -> p.test(param))) {
matches.add(param); matches.add(param);
} }

56
spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMapMethodArgumentResolverTests.java

@ -16,15 +16,14 @@
package org.springframework.web.method.annotation; package org.springframework.web.method.annotation;
import java.lang.reflect.Method;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import org.junit.Before; 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.annotation.SynthesizingMethodParameter;
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.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
@ -32,6 +31,7 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
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.method.ResolvableMethod;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -45,29 +45,17 @@ public class RequestParamMapMethodArgumentResolverTests {
private RequestParamMapMethodArgumentResolver resolver; private RequestParamMapMethodArgumentResolver resolver;
private MethodParameter paramMap;
private MethodParameter paramMultiValueMap;
private MethodParameter paramNamedMap;
private MethodParameter paramMapWithoutAnnot;
private NativeWebRequest webRequest; private NativeWebRequest webRequest;
private MockHttpServletRequest request; private MockHttpServletRequest request;
private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build();
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
resolver = new RequestParamMapMethodArgumentResolver(); resolver = new RequestParamMapMethodArgumentResolver();
Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, Map.class, Map.class);
paramMap = new SynthesizingMethodParameter(method, 0);
paramMultiValueMap = new SynthesizingMethodParameter(method, 1);
paramNamedMap = new SynthesizingMethodParameter(method, 2);
paramMapWithoutAnnot = new SynthesizingMethodParameter(method, 3);
request = new MockHttpServletRequest(); request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
} }
@ -75,10 +63,17 @@ public class RequestParamMapMethodArgumentResolverTests {
@Test @Test
public void supportsParameter() { public void supportsParameter() {
assertTrue("Map parameter not supported", resolver.supportsParameter(paramMap)); MethodParameter param = this.testMethod.annotated(RequestParam.class, name("")).arg(Map.class);
assertTrue("MultiValueMap parameter not supported", resolver.supportsParameter(paramMultiValueMap)); assertTrue(resolver.supportsParameter(param));
assertFalse("Map with name supported", resolver.supportsParameter(paramNamedMap));
assertFalse("non-@RequestParam map supported", resolver.supportsParameter(paramMapWithoutAnnot)); param = this.testMethod.annotated(RequestParam.class).arg(MultiValueMap.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, name("name")).arg(Map.class);
assertFalse(resolver.supportsParameter(param));
param = this.testMethod.notAnnotated(RequestParam.class).arg(Map.class);
assertFalse(resolver.supportsParameter(param));
} }
@Test @Test
@ -88,7 +83,8 @@ public class RequestParamMapMethodArgumentResolverTests {
request.addParameter(name, value); request.addParameter(name, value);
Map<String, String> expected = Collections.singletonMap(name, value); Map<String, String> expected = Collections.singletonMap(name, value);
Object result = resolver.resolveArgument(paramMap, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class, name("")).arg(Map.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof Map); assertTrue(result instanceof Map);
assertEquals("Invalid result", expected, result); assertEquals("Invalid result", expected, result);
@ -99,23 +95,29 @@ public class RequestParamMapMethodArgumentResolverTests {
String name = "foo"; String name = "foo";
String value1 = "bar"; String value1 = "bar";
String value2 = "baz"; String value2 = "baz";
request.addParameter(name, new String[]{value1, value2}); request.addParameter(name, value1, value2);
MultiValueMap<String, String> expected = new LinkedMultiValueMap<>(1); MultiValueMap<String, String> expected = new LinkedMultiValueMap<>(1);
expected.add(name, value1); expected.add(name, value1);
expected.add(name, value2); expected.add(name, value2);
Object result = resolver.resolveArgument(paramMultiValueMap, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(MultiValueMap.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof MultiValueMap); assertTrue(result instanceof MultiValueMap);
assertEquals("Invalid result", expected, result); assertEquals("Invalid result", expected, result);
} }
private Predicate<RequestParam> name(String name) {
return a -> name.equals(a.name());
}
public void params(@RequestParam Map<?, ?> param1, public void handle(
@RequestParam MultiValueMap<?, ?> param2, @RequestParam Map<?, ?> param1,
@RequestParam("name") Map<?, ?> param3, @RequestParam MultiValueMap<?, ?> param2,
Map<?, ?> param4) { @RequestParam("name") Map<?, ?> param3,
Map<?, ?> param4) {
} }
} }

287
spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java

@ -16,11 +16,11 @@
package org.springframework.web.method.annotation; package org.springframework.web.method.annotation;
import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate;
import javax.servlet.http.Part; import javax.servlet.http.Part;
import org.junit.Before; import org.junit.Before;
@ -29,31 +29,37 @@ import org.junit.Test;
import org.springframework.beans.propertyeditors.StringTrimmerEditor; import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.DefaultConversionService;
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.mock.web.test.MockMultipartFile; import org.springframework.mock.web.test.MockMultipartFile;
import org.springframework.mock.web.test.MockMultipartHttpServletRequest; import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
import org.springframework.mock.web.test.MockPart; import org.springframework.mock.web.test.MockPart;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.bind.support.DefaultDataBinderFactory; import org.springframework.web.bind.support.DefaultDataBinderFactory;
import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.bind.support.WebRequestDataBinder; import org.springframework.web.bind.support.WebRequestDataBinder;
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.method.ResolvableMethod;
import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.multipart.support.MissingServletRequestPartException;
import static org.junit.Assert.*; import static org.junit.Assert.assertArrayEquals;
import static org.mockito.BDDMockito.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
import static org.springframework.core.ResolvableType.forClassWithGenerics;
/** /**
* Test fixture with {@link org.springframework.web.method.annotation.RequestParamMethodArgumentResolver}. * Test fixture with {@link org.springframework.web.method.annotation.RequestParamMethodArgumentResolver}.
@ -66,92 +72,87 @@ public class RequestParamMethodArgumentResolverTests {
private RequestParamMethodArgumentResolver resolver; private RequestParamMethodArgumentResolver resolver;
private MethodParameter paramNamedDefaultValueString;
private MethodParameter paramNamedStringArray;
private MethodParameter paramNamedMap;
private MethodParameter paramMultipartFile;
private MethodParameter paramMultipartFileList;
private MethodParameter paramMultipartFileArray;
private MethodParameter paramPart;
private MethodParameter paramPartList;
private MethodParameter paramPartArray;
private MethodParameter paramMap;
private MethodParameter paramStringNotAnnot;
private MethodParameter paramMultipartFileNotAnnot;
private MethodParameter paramMultipartFileListNotAnnot;
private MethodParameter paramPartNotAnnot;
private MethodParameter paramRequestPartAnnot;
private MethodParameter paramRequired;
private MethodParameter paramNotRequired;
private MethodParameter paramOptional;
private MethodParameter multipartFileOptional;
private NativeWebRequest webRequest; private NativeWebRequest webRequest;
private MockHttpServletRequest request; private MockHttpServletRequest request;
private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build();
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
resolver = new RequestParamMethodArgumentResolver(null, true); resolver = new RequestParamMethodArgumentResolver(null, true);
ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class<?>[]) null);
paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0);
paramNamedStringArray = new SynthesizingMethodParameter(method, 1);
paramNamedMap = new SynthesizingMethodParameter(method, 2);
paramMultipartFile = new SynthesizingMethodParameter(method, 3);
paramMultipartFileList = new SynthesizingMethodParameter(method, 4);
paramMultipartFileArray = new SynthesizingMethodParameter(method, 5);
paramPart = new SynthesizingMethodParameter(method, 6);
paramPartList = new SynthesizingMethodParameter(method, 7);
paramPartArray = new SynthesizingMethodParameter(method, 8);
paramMap = new SynthesizingMethodParameter(method, 9);
paramStringNotAnnot = new SynthesizingMethodParameter(method, 10);
paramStringNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramMultipartFileNotAnnot = new SynthesizingMethodParameter(method, 11);
paramMultipartFileNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramMultipartFileListNotAnnot = new SynthesizingMethodParameter(method, 12);
paramMultipartFileListNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramPartNotAnnot = new SynthesizingMethodParameter(method, 13);
paramPartNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramRequestPartAnnot = new SynthesizingMethodParameter(method, 14);
paramRequired = new SynthesizingMethodParameter(method, 15);
paramNotRequired = new SynthesizingMethodParameter(method, 16);
paramOptional = new SynthesizingMethodParameter(method, 17);
multipartFileOptional = new SynthesizingMethodParameter(method, 18);
request = new MockHttpServletRequest(); request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
} }
@Test @Test
public void supportsParameter() { public void supportsParameter() {
resolver = new RequestParamMethodArgumentResolver(null, true); resolver = new RequestParamMethodArgumentResolver(null, true);
assertTrue(resolver.supportsParameter(paramNamedDefaultValueString));
assertTrue(resolver.supportsParameter(paramNamedStringArray)); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
assertTrue(resolver.supportsParameter(paramNamedMap)); assertTrue(resolver.supportsParameter(param));
assertTrue(resolver.supportsParameter(paramMultipartFile));
assertTrue(resolver.supportsParameter(paramMultipartFileList)); param = this.testMethod.annotated(RequestParam.class).arg(String[].class);
assertTrue(resolver.supportsParameter(paramMultipartFileArray)); assertTrue(resolver.supportsParameter(param));
assertTrue(resolver.supportsParameter(paramPart));
assertTrue(resolver.supportsParameter(paramPartList)); param = this.testMethod.annotated(RequestParam.class, name("name")).arg(Map.class);
assertTrue(resolver.supportsParameter(paramPartArray)); assertTrue(resolver.supportsParameter(param));
assertFalse(resolver.supportsParameter(paramMap));
assertTrue(resolver.supportsParameter(paramStringNotAnnot)); param = this.testMethod.annotated(RequestParam.class).arg(MultipartFile.class);
assertTrue(resolver.supportsParameter(paramMultipartFileNotAnnot)); assertTrue(resolver.supportsParameter(param));
assertTrue(resolver.supportsParameter(paramMultipartFileListNotAnnot));
assertTrue(resolver.supportsParameter(paramPartNotAnnot)); param = this.testMethod.annotated(RequestParam.class).arg(forClassWithGenerics(List.class, MultipartFile.class));
assertFalse(resolver.supportsParameter(paramRequestPartAnnot)); assertTrue(resolver.supportsParameter(param));
assertTrue(resolver.supportsParameter(paramRequired));
assertTrue(resolver.supportsParameter(paramNotRequired)); param = this.testMethod.annotated(RequestParam.class).arg(MultipartFile[].class);
assertTrue(resolver.supportsParameter(paramOptional)); assertTrue(resolver.supportsParameter(param));
assertTrue(resolver.supportsParameter(multipartFileOptional));
param = this.testMethod.annotated(RequestParam.class).arg(Part.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class).arg(forClassWithGenerics(List.class, Part.class));
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class).arg(Part[].class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, name("")).arg(Map.class);
assertFalse(resolver.supportsParameter(param));
param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.notAnnotated().arg(MultipartFile.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.notAnnotated(RequestParam.class).arg(forClassWithGenerics(List.class, MultipartFile.class));
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.notAnnotated(RequestParam.class).arg(Part.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestPart.class).arg(MultipartFile.class);
assertFalse(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, required(), value("")).arg(String.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, required().negate()).arg(String.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class).arg(forClassWithGenerics(Optional.class, Integer.class));
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class).arg(forClassWithGenerics(Optional.class, MultipartFile.class));
assertTrue(resolver.supportsParameter(param));
resolver = new RequestParamMethodArgumentResolver(null, false); resolver = new RequestParamMethodArgumentResolver(null, false);
assertFalse(resolver.supportsParameter(paramStringNotAnnot));
assertFalse(resolver.supportsParameter(paramRequestPartAnnot)); param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
assertFalse(resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestPart.class).arg(MultipartFile.class);
assertFalse(resolver.supportsParameter(param));
} }
@Test @Test
@ -159,7 +160,8 @@ public class RequestParamMethodArgumentResolverTests {
String expected = "foo"; String expected = "foo";
request.addParameter("name", expected); request.addParameter("name", expected);
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof String); assertTrue(result instanceof String);
assertEquals("Invalid result", expected, result); assertEquals("Invalid result", expected, result);
} }
@ -169,7 +171,8 @@ public class RequestParamMethodArgumentResolverTests {
String[] expected = new String[] {"foo", "bar"}; String[] expected = new String[] {"foo", "bar"};
request.addParameter("name", expected); request.addParameter("name", expected);
Object result = resolver.resolveArgument(paramNamedStringArray, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(String[].class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof String[]); assertTrue(result instanceof String[]);
assertArrayEquals("Invalid result", expected, (String[]) result); assertArrayEquals("Invalid result", expected, (String[]) result);
} }
@ -181,7 +184,8 @@ public class RequestParamMethodArgumentResolverTests {
request.addFile(expected); request.addFile(expected);
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFile, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(MultipartFile.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof MultipartFile); assertTrue(result instanceof MultipartFile);
assertEquals("Invalid result", expected, result); assertEquals("Invalid result", expected, result);
} }
@ -196,7 +200,11 @@ public class RequestParamMethodArgumentResolverTests {
request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes())); request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileList, null, webRequest, null); MethodParameter param = this.testMethod
.annotated(RequestParam.class)
.arg(forClassWithGenerics(List.class, MultipartFile.class));
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof List); assertTrue(result instanceof List);
assertEquals(Arrays.asList(expected1, expected2), result); assertEquals(Arrays.asList(expected1, expected2), result);
} }
@ -211,7 +219,8 @@ public class RequestParamMethodArgumentResolverTests {
request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes())); request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileArray, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(MultipartFile[].class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof MultipartFile[]); assertTrue(result instanceof MultipartFile[]);
MultipartFile[] parts = (MultipartFile[]) result; MultipartFile[] parts = (MultipartFile[]) result;
assertEquals(2, parts.length); assertEquals(2, parts.length);
@ -228,7 +237,8 @@ public class RequestParamMethodArgumentResolverTests {
request.addPart(expected); request.addPart(expected);
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPart, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(Part.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof Part); assertTrue(result instanceof Part);
assertEquals("Invalid result", expected, result); assertEquals("Invalid result", expected, result);
} }
@ -245,7 +255,11 @@ public class RequestParamMethodArgumentResolverTests {
request.addPart(new MockPart("other", "Hello World 3".getBytes())); request.addPart(new MockPart("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartList, null, webRequest, null); MethodParameter param = this.testMethod
.annotated(RequestParam.class)
.arg(forClassWithGenerics(List.class, Part.class));
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof List); assertTrue(result instanceof List);
assertEquals(Arrays.asList(expected1, expected2), result); assertEquals(Arrays.asList(expected1, expected2), result);
} }
@ -262,7 +276,8 @@ public class RequestParamMethodArgumentResolverTests {
request.addPart(new MockPart("other", "Hello World 3".getBytes())); request.addPart(new MockPart("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartArray, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(Part[].class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof Part[]); assertTrue(result instanceof Part[]);
Part[] parts = (Part[]) result; Part[] parts = (Part[]) result;
assertEquals(2, parts.length); assertEquals(2, parts.length);
@ -277,7 +292,10 @@ public class RequestParamMethodArgumentResolverTests {
request.addFile(expected); request.addFile(expected);
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileNotAnnot, null, webRequest, null); MethodParameter param = this.testMethod.notAnnotated().arg(MultipartFile.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof MultipartFile); assertTrue(result instanceof MultipartFile);
assertEquals("Invalid result", expected, result); assertEquals("Invalid result", expected, result);
} }
@ -291,14 +309,20 @@ public class RequestParamMethodArgumentResolverTests {
request.addFile(expected2); request.addFile(expected2);
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null); MethodParameter param = this.testMethod
.notAnnotated(RequestParam.class)
.arg(forClassWithGenerics(List.class, MultipartFile.class));
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof List); assertTrue(result instanceof List);
assertEquals(Arrays.asList(expected1, expected2), result); assertEquals(Arrays.asList(expected1, expected2), result);
} }
@Test(expected = MultipartException.class) @Test(expected = MultipartException.class)
public void isMultipartRequest() throws Exception { public void isMultipartRequest() throws Exception {
resolver.resolveArgument(paramMultipartFile, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(MultipartFile.class);
resolver.resolveArgument(param, null, webRequest, null);
fail("Expected exception: request is not a multipart request"); fail("Expected exception: request is not a multipart request");
} }
@ -310,7 +334,12 @@ public class RequestParamMethodArgumentResolverTests {
request.setMethod("PUT"); request.setMethod("PUT");
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object actual = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null); MethodParameter param = this.testMethod
.notAnnotated(RequestParam.class)
.arg(forClassWithGenerics(List.class, MultipartFile.class));
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object actual = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(actual instanceof List); assertTrue(actual instanceof List);
assertEquals(expected, ((List<?>) actual).get(0)); assertEquals(expected, ((List<?>) actual).get(0));
} }
@ -318,7 +347,8 @@ public class RequestParamMethodArgumentResolverTests {
@Test(expected = MultipartException.class) @Test(expected = MultipartException.class)
public void noMultipartContent() throws Exception { public void noMultipartContent() throws Exception {
request.setMethod("POST"); request.setMethod("POST");
resolver.resolveArgument(paramMultipartFile, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(MultipartFile.class);
resolver.resolveArgument(param, null, webRequest, null);
fail("Expected exception: no multipart content"); fail("Expected exception: no multipart content");
} }
@ -326,7 +356,8 @@ public class RequestParamMethodArgumentResolverTests {
public void missingMultipartFile() throws Exception { public void missingMultipartFile() throws Exception {
request.setMethod("POST"); request.setMethod("POST");
request.setContentType("multipart/form-data"); request.setContentType("multipart/form-data");
resolver.resolveArgument(paramMultipartFile, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(MultipartFile.class);
resolver.resolveArgument(param, null, webRequest, null);
fail("Expected exception: no such part found"); fail("Expected exception: no such part found");
} }
@ -339,21 +370,25 @@ public class RequestParamMethodArgumentResolverTests {
request.addPart(expected); request.addPart(expected);
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartNotAnnot, null, webRequest, null); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(Part.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof Part); assertTrue(result instanceof Part);
assertEquals("Invalid result", expected, result); assertEquals("Invalid result", expected, result);
} }
@Test @Test
public void resolveDefaultValue() throws Exception { public void resolveDefaultValue() throws Exception {
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof String); assertTrue(result instanceof String);
assertEquals("Invalid result", "bar", result); assertEquals("Invalid result", "bar", result);
} }
@Test(expected = MissingServletRequestParameterException.class) @Test(expected = MissingServletRequestParameterException.class)
public void missingRequestParam() throws Exception { public void missingRequestParam() throws Exception {
resolver.resolveArgument(paramNamedStringArray, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(String[].class);
resolver.resolveArgument(param, null, webRequest, null);
fail("Expected exception"); fail("Expected exception");
} }
@ -367,7 +402,9 @@ public class RequestParamMethodArgumentResolverTests {
this.request.addParameter("stringNotAnnot", ""); this.request.addParameter("stringNotAnnot", "");
Object arg = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, binderFactory); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object arg = resolver.resolveArgument(param, null, webRequest, binderFactory);
assertNull(arg); assertNull(arg);
} }
@ -381,14 +418,18 @@ public class RequestParamMethodArgumentResolverTests {
this.request.addParameter("name", ""); this.request.addParameter("name", "");
Object arg = resolver.resolveArgument(paramNotRequired, null, webRequest, binderFactory); MethodParameter param = this.testMethod.annotated(RequestParam.class, required().negate()).arg(String.class);
Object arg = resolver.resolveArgument(param, null, webRequest, binderFactory);
assertNull(arg); assertNull(arg);
} }
@Test @Test
public void resolveSimpleTypeParam() throws Exception { public void resolveSimpleTypeParam() throws Exception {
request.setParameter("stringNotAnnot", "plainValue"); request.setParameter("stringNotAnnot", "plainValue");
Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object result = resolver.resolveArgument(param, null, webRequest, null);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
assertTrue(result instanceof String); assertTrue(result instanceof String);
assertEquals("plainValue", result); assertEquals("plainValue", result);
@ -396,28 +437,34 @@ public class RequestParamMethodArgumentResolverTests {
@Test // SPR-8561 @Test // SPR-8561
public void resolveSimpleTypeParamToNull() throws Exception { public void resolveSimpleTypeParamToNull() throws Exception {
Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertNull(result); assertNull(result);
} }
@Test // SPR-10180 @Test // SPR-10180
public void resolveEmptyValueToDefault() throws Exception { public void resolveEmptyValueToDefault() throws Exception {
this.request.addParameter("name", ""); this.request.addParameter("name", "");
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertEquals("bar", result); assertEquals("bar", result);
} }
@Test @Test
public void resolveEmptyValueWithoutDefault() throws Exception { public void resolveEmptyValueWithoutDefault() throws Exception {
this.request.addParameter("stringNotAnnot", ""); this.request.addParameter("stringNotAnnot", "");
Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertEquals("", result); assertEquals("", result);
} }
@Test @Test
public void resolveEmptyValueRequiredWithoutDefault() throws Exception { public void resolveEmptyValueRequiredWithoutDefault() throws Exception {
this.request.addParameter("name", ""); this.request.addParameter("name", "");
Object result = resolver.resolveArgument(paramRequired, null, webRequest, null); MethodParameter param = this.testMethod.annotated(RequestParam.class, required(), value("")).arg(String.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertEquals("", result); assertEquals("", result);
} }
@ -428,11 +475,15 @@ public class RequestParamMethodArgumentResolverTests {
initializer.setConversionService(new DefaultConversionService()); initializer.setConversionService(new DefaultConversionService());
WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer); WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
Object result = resolver.resolveArgument(paramOptional, null, webRequest, binderFactory); MethodParameter param = this.testMethod
.annotated(RequestParam.class)
.arg(forClassWithGenerics(Optional.class, Integer.class));
Object result = resolver.resolveArgument(param, null, webRequest, binderFactory);
assertEquals(Optional.empty(), result); assertEquals(Optional.empty(), result);
this.request.addParameter("name", "123"); this.request.addParameter("name", "123");
result = resolver.resolveArgument(paramOptional, null, webRequest, binderFactory); result = resolver.resolveArgument(param, null, webRequest, binderFactory);
assertEquals(Optional.class, result.getClass()); assertEquals(Optional.class, result.getClass());
assertEquals(123, ((Optional) result).get()); assertEquals(123, ((Optional) result).get());
} }
@ -448,7 +499,11 @@ public class RequestParamMethodArgumentResolverTests {
request.addFile(expected); request.addFile(expected);
webRequest = new ServletWebRequest(request); webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory); MethodParameter param = this.testMethod
.annotated(RequestParam.class)
.arg(forClassWithGenerics(Optional.class, MultipartFile.class));
Object result = resolver.resolveArgument(param, null, webRequest, binderFactory);
assertTrue(result instanceof Optional); assertTrue(result instanceof Optional);
assertEquals("Invalid result", expected, ((Optional<?>) result).get()); assertEquals("Invalid result", expected, ((Optional<?>) result).get());
} }
@ -461,7 +516,12 @@ public class RequestParamMethodArgumentResolverTests {
request.setMethod("POST"); request.setMethod("POST");
request.setContentType("multipart/form-data"); request.setContentType("multipart/form-data");
assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory));
MethodParameter param = this.testMethod
.annotated(RequestParam.class)
.arg(forClassWithGenerics(Optional.class, MultipartFile.class));
assertEquals(Optional.empty(), resolver.resolveArgument(param, null, webRequest, binderFactory));
} }
@Test @Test
@ -470,10 +530,29 @@ public class RequestParamMethodArgumentResolverTests {
initializer.setConversionService(new DefaultConversionService()); initializer.setConversionService(new DefaultConversionService());
WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer); WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory)); MethodParameter param = this.testMethod
.annotated(RequestParam.class)
.arg(forClassWithGenerics(Optional.class, MultipartFile.class));
assertEquals(Optional.empty(), resolver.resolveArgument(param, null, webRequest, binderFactory));
}
private Predicate<RequestParam> name(String name) {
return a -> name.equals(a.name());
}
private Predicate<RequestParam> required() {
return RequestParam::required;
}
private Predicate<RequestParam> value(String value) {
return !value.isEmpty() ?
requestParam -> value.equals(requestParam.defaultValue()) :
requestParam -> ValueConstants.DEFAULT_NONE.equals(requestParam.defaultValue());
} }
@SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType"})
public void handle( public void handle(
@RequestParam(name = "name", defaultValue = "bar") String param1, @RequestParam(name = "name", defaultValue = "bar") String param1,
@RequestParam("name") String[] param2, @RequestParam("name") String[] param2,

54
spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolverTests.java

@ -16,22 +16,22 @@
package org.springframework.web.reactive.result.method.annotation; package org.springframework.web.reactive.result.method.annotation;
import java.lang.reflect.Method;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import org.junit.Before; 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.annotation.SynthesizingMethodParameter;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.method.ResolvableMethod;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange;
@ -47,50 +47,51 @@ public class RequestParamMapMethodArgumentResolverTests {
private RequestParamMapMethodArgumentResolver resolver; private RequestParamMapMethodArgumentResolver resolver;
private MethodParameter paramMap; private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build();
private MethodParameter paramMultiValueMap;
private MethodParameter paramNamedMap;
private MethodParameter paramMapWithoutAnnot;
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
this.resolver = new RequestParamMapMethodArgumentResolver(); this.resolver = new RequestParamMapMethodArgumentResolver();
Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, Map.class, Map.class);
this.paramMap = new SynthesizingMethodParameter(method, 0);
this.paramMultiValueMap = new SynthesizingMethodParameter(method, 1);
this.paramNamedMap = new SynthesizingMethodParameter(method, 2);
this.paramMapWithoutAnnot = new SynthesizingMethodParameter(method, 3);
} }
@Test @Test
public void supportsParameter() { public void supportsParameter() {
assertTrue(this.resolver.supportsParameter(this.paramMap)); MethodParameter param = this.testMethod.annotated(RequestParam.class, name("")).arg(Map.class);
assertTrue(this.resolver.supportsParameter(this.paramMultiValueMap)); assertTrue(this.resolver.supportsParameter(param));
assertFalse(this.resolver.supportsParameter(this.paramNamedMap));
assertFalse(this.resolver.supportsParameter(this.paramMapWithoutAnnot)); param = this.testMethod.annotated(RequestParam.class).arg(MultiValueMap.class);
assertTrue(this.resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, name("name")).arg(Map.class);
assertFalse(this.resolver.supportsParameter(param));
param = this.testMethod.notAnnotated(RequestParam.class).arg(Map.class);
assertFalse(this.resolver.supportsParameter(param));
} }
@Test @Test
public void resolveMapArgumentWithQueryString() throws Exception { public void resolveMapArgumentWithQueryString() throws Exception {
Object result= resolve(this.paramMap, exchangeWithQuery("foo=bar")); MethodParameter param = this.testMethod.annotated(RequestParam.class, name("")).arg(Map.class);
Object result= resolve(param, exchangeWithQuery("foo=bar"));
assertTrue(result instanceof Map); assertTrue(result instanceof Map);
assertEquals(Collections.singletonMap("foo", "bar"), result); assertEquals(Collections.singletonMap("foo", "bar"), result);
} }
@Test @Test
public void resolveMapArgumentWithFormData() throws Exception { public void resolveMapArgumentWithFormData() throws Exception {
Object result= resolve(this.paramMap, exchangeWithFormData("foo=bar")); MethodParameter param = this.testMethod.annotated(RequestParam.class, name("")).arg(Map.class);
Object result= resolve(param, exchangeWithFormData("foo=bar"));
assertTrue(result instanceof Map); assertTrue(result instanceof Map);
assertEquals(Collections.singletonMap("foo", "bar"), result); assertEquals(Collections.singletonMap("foo", "bar"), result);
} }
@Test @Test
public void resolveMultiValueMapArgument() throws Exception { public void resolveMultiValueMapArgument() throws Exception {
MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(MultiValueMap.class);
ServerWebExchange exchange = exchangeWithQuery("foo=bar&foo=baz"); ServerWebExchange exchange = exchangeWithQuery("foo=bar&foo=baz");
Object result= resolve(this.paramMultiValueMap, exchange); Object result= resolve(param, exchange);
assertTrue(result instanceof MultiValueMap); assertTrue(result instanceof MultiValueMap);
assertEquals(Collections.singletonMap("foo", Arrays.asList("bar", "baz")), result); assertEquals(Collections.singletonMap("foo", Arrays.asList("bar", "baz")), result);
@ -113,12 +114,17 @@ public class RequestParamMapMethodArgumentResolverTests {
return this.resolver.resolveArgument(parameter, null, exchange).blockMillis(0); return this.resolver.resolveArgument(parameter, null, exchange).blockMillis(0);
} }
private Predicate<RequestParam> name(String name) {
return a -> name.equals(a.name());
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void params(@RequestParam Map<?, ?> param1, public void handle(
@RequestParam MultiValueMap<?, ?> param2, @RequestParam Map<?, ?> param1,
@RequestParam("name") Map<?, ?> param3, @RequestParam MultiValueMap<?, ?> param2,
Map<?, ?> param4) { @RequestParam("name") Map<?, ?> param3,
Map<?, ?> param4) {
} }
} }

128
spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java

@ -16,10 +16,10 @@
package org.springframework.web.reactive.result.method.annotation; package org.springframework.web.reactive.result.method.annotation;
import java.lang.reflect.Method;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -28,21 +28,25 @@ import reactor.test.StepVerifier;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.method.ResolvableMethod;
import org.springframework.web.reactive.BindingContext; import org.springframework.web.reactive.BindingContext;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.ServerWebInputException;
import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange;
import static org.junit.Assert.*; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.core.ResolvableType.forClassWithGenerics;
/** /**
* Unit tests for {@link RequestParamMethodArgumentResolver}. * Unit tests for {@link RequestParamMethodArgumentResolver}.
@ -53,34 +57,15 @@ public class RequestParamMethodArgumentResolverTests {
private RequestParamMethodArgumentResolver resolver; private RequestParamMethodArgumentResolver resolver;
private MethodParameter paramNamedDefaultValueString;
private MethodParameter paramNamedStringArray;
private MethodParameter paramNamedMap;
private MethodParameter paramMap;
private MethodParameter paramStringNotAnnot;
private MethodParameter paramRequired;
private MethodParameter paramNotRequired;
private MethodParameter paramOptional;
private BindingContext bindContext; private BindingContext bindContext;
private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build();
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
this.resolver = new RequestParamMethodArgumentResolver(null, true);
ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); this.resolver = new RequestParamMethodArgumentResolver(null, true);
Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class<?>[]) null);
this.paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0);
this.paramNamedStringArray = new SynthesizingMethodParameter(method, 1);
this.paramNamedMap = new SynthesizingMethodParameter(method, 2);
this.paramMap = new SynthesizingMethodParameter(method, 3);
this.paramStringNotAnnot = new SynthesizingMethodParameter(method, 4);
this.paramStringNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
this.paramRequired = new SynthesizingMethodParameter(method, 5);
this.paramNotRequired = new SynthesizingMethodParameter(method, 6);
this.paramOptional = new SynthesizingMethodParameter(method, 7);
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer(); ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
initializer.setConversionService(new DefaultFormattingConversionService()); initializer.setConversionService(new DefaultFormattingConversionService());
@ -91,47 +76,64 @@ public class RequestParamMethodArgumentResolverTests {
@Test @Test
public void supportsParameter() { public void supportsParameter() {
this.resolver = new RequestParamMethodArgumentResolver(null, true); this.resolver = new RequestParamMethodArgumentResolver(null, true);
assertTrue(this.resolver.supportsParameter(this.paramNamedDefaultValueString));
assertTrue(this.resolver.supportsParameter(this.paramNamedStringArray));
assertTrue(this.resolver.supportsParameter(this.paramNamedMap));
assertFalse(this.resolver.supportsParameter(this.paramMap));
assertTrue(this.resolver.supportsParameter(this.paramStringNotAnnot));
assertTrue(this.resolver.supportsParameter(this.paramRequired));
assertTrue(this.resolver.supportsParameter(this.paramNotRequired));
assertTrue(this.resolver.supportsParameter(this.paramOptional));
MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
assertTrue(this.resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class).arg(String[].class);
assertTrue(this.resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, name("name")).arg(Map.class);
assertTrue(this.resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, name("")).arg(Map.class);
assertFalse(this.resolver.supportsParameter(param));
param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
assertTrue(this.resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, required(), value("")).arg(String.class);
assertTrue(this.resolver.supportsParameter(param));
param = this.testMethod.annotated(RequestParam.class, required().negate()).arg(String.class);
assertTrue(this.resolver.supportsParameter(param));
param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
this.resolver = new RequestParamMethodArgumentResolver(null, false); this.resolver = new RequestParamMethodArgumentResolver(null, false);
assertFalse(this.resolver.supportsParameter(this.paramStringNotAnnot)); assertFalse(this.resolver.supportsParameter(param));
} }
@Test @Test
public void resolveWithQueryString() throws Exception { public void resolveWithQueryString() throws Exception {
assertEquals("foo", resolve(this.paramNamedDefaultValueString, exchangeWithQuery("name=foo"))); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
assertEquals("foo", resolve(param, exchangeWithQuery("name=foo")));
} }
@Test @Test
public void resolveWithFormData() throws Exception { public void resolveWithFormData() throws Exception {
assertEquals("foo", resolve(this.paramNamedDefaultValueString, exchangeWithFormData("name=foo"))); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
assertEquals("foo", resolve(param, exchangeWithFormData("name=foo")));
} }
@Test @Test
public void resolveStringArray() throws Exception { public void resolveStringArray() throws Exception {
Object result = resolve(this.paramNamedStringArray, exchangeWithQuery("name=foo&name=bar")); MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(String[].class);
Object result = resolve(param, exchangeWithQuery("name=foo&name=bar"));
assertTrue(result instanceof String[]); assertTrue(result instanceof String[]);
assertArrayEquals(new String[] {"foo", "bar"}, (String[]) result); assertArrayEquals(new String[] {"foo", "bar"}, (String[]) result);
} }
@Test @Test
public void resolveDefaultValue() throws Exception { public void resolveDefaultValue() throws Exception {
Object result = resolve(this.paramNamedDefaultValueString, exchange()); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
assertEquals("bar", result); assertEquals("bar", resolve(param, exchange()));
} }
@Test @Test
public void missingRequestParam() throws Exception { public void missingRequestParam() throws Exception {
Mono<Object> mono = this.resolver.resolveArgument( MethodParameter param = this.testMethod.annotated(RequestParam.class).arg(String[].class);
this.paramNamedStringArray, this.bindContext, exchange()); Mono<Object> mono = this.resolver.resolveArgument(param, this.bindContext, exchange());
StepVerifier.create(mono) StepVerifier.create(mono)
.expectNextCount(0) .expectNextCount(0)
@ -142,40 +144,52 @@ public class RequestParamMethodArgumentResolverTests {
@Test @Test
public void resolveSimpleTypeParam() throws Exception { public void resolveSimpleTypeParam() throws Exception {
ServerWebExchange exchange = exchangeWithQuery("stringNotAnnot=plainValue"); ServerWebExchange exchange = exchangeWithQuery("stringNotAnnot=plainValue");
Object result = resolve(this.paramStringNotAnnot, exchange); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
Object result = resolve(param, exchange);
assertEquals("plainValue", result); assertEquals("plainValue", result);
} }
@Test // SPR-8561 @Test // SPR-8561
public void resolveSimpleTypeParamToNull() throws Exception { public void resolveSimpleTypeParamToNull() throws Exception {
assertNull(resolve(this.paramStringNotAnnot, exchange())); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
assertNull(resolve(param, exchange()));
} }
@Test // SPR-10180 @Test // SPR-10180
public void resolveEmptyValueToDefault() throws Exception { public void resolveEmptyValueToDefault() throws Exception {
ServerWebExchange exchange = exchangeWithQuery("name="); ServerWebExchange exchange = exchangeWithQuery("name=");
Object result = resolve(this.paramNamedDefaultValueString, exchange); MethodParameter param = this.testMethod.annotated(RequestParam.class, value("bar")).arg(String.class);
Object result = resolve(param, exchange);
assertEquals("bar", result); assertEquals("bar", result);
} }
@Test @Test
public void resolveEmptyValueWithoutDefault() throws Exception { public void resolveEmptyValueWithoutDefault() throws Exception {
assertEquals("", resolve(this.paramStringNotAnnot, exchangeWithQuery("stringNotAnnot="))); MethodParameter param = this.testMethod.notAnnotated(RequestParam.class).arg(String.class);
param.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
assertEquals("", resolve(param, exchangeWithQuery("stringNotAnnot=")));
} }
@Test @Test
public void resolveEmptyValueRequiredWithoutDefault() throws Exception { public void resolveEmptyValueRequiredWithoutDefault() throws Exception {
assertEquals("", resolve(this.paramRequired, exchangeWithQuery("name="))); MethodParameter param = this.testMethod
.annotated(RequestParam.class, required(), value(""))
.arg(String.class);
assertEquals("", resolve(param, exchangeWithQuery("name=")));
} }
@Test @Test
public void resolveOptionalParamValue() throws Exception { public void resolveOptionalParamValue() throws Exception {
ServerWebExchange exchange = exchange(); ServerWebExchange exchange = exchange();
Object result = resolve(this.paramOptional, exchange); MethodParameter param = this.testMethod.arg(forClassWithGenerics(Optional.class, Integer.class));
Object result = resolve(param, exchange);
assertEquals(Optional.empty(), result); assertEquals(Optional.empty(), result);
exchange = exchangeWithQuery("name=123"); exchange = exchangeWithQuery("name=123");
result = resolve(this.paramOptional, exchange); result = resolve(param, exchange);
assertEquals(Optional.class, result.getClass()); assertEquals(Optional.class, result.getClass());
Optional<?> value = (Optional<?>) result; Optional<?> value = (Optional<?>) result;
@ -205,6 +219,20 @@ public class RequestParamMethodArgumentResolverTests {
return this.resolver.resolveArgument(parameter, this.bindContext, exchange).blockMillis(0); return this.resolver.resolveArgument(parameter, this.bindContext, exchange).blockMillis(0);
} }
private Predicate<RequestParam> name(String name) {
return a -> name.equals(a.name());
}
private Predicate<RequestParam> required() {
return RequestParam::required;
}
private Predicate<RequestParam> value(String value) {
return !value.isEmpty() ?
requestParam -> value.equals(requestParam.defaultValue()) :
requestParam -> ValueConstants.DEFAULT_NONE.equals(requestParam.defaultValue());
}
@SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType"}) @SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType"})
public void handle( public void handle(

Loading…
Cancel
Save