1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.method.annotation;
18
19 import java.lang.reflect.Method;
20 import java.util.Arrays;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Optional;
24 import javax.servlet.http.Part;
25
26 import org.junit.Before;
27 import org.junit.Test;
28
29 import org.springframework.beans.propertyeditors.StringTrimmerEditor;
30 import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
31 import org.springframework.core.MethodParameter;
32 import org.springframework.core.ParameterNameDiscoverer;
33 import org.springframework.core.convert.support.DefaultConversionService;
34 import org.springframework.mock.web.test.MockHttpServletRequest;
35 import org.springframework.mock.web.test.MockHttpServletResponse;
36 import org.springframework.mock.web.test.MockMultipartFile;
37 import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
38 import org.springframework.mock.web.test.MockPart;
39 import org.springframework.web.bind.MissingServletRequestParameterException;
40 import org.springframework.web.bind.WebDataBinder;
41 import org.springframework.web.bind.annotation.RequestParam;
42 import org.springframework.web.bind.annotation.RequestPart;
43 import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
44 import org.springframework.web.bind.support.DefaultDataBinderFactory;
45 import org.springframework.web.bind.support.WebDataBinderFactory;
46 import org.springframework.web.bind.support.WebRequestDataBinder;
47 import org.springframework.web.context.request.NativeWebRequest;
48 import org.springframework.web.context.request.ServletWebRequest;
49 import org.springframework.web.multipart.MultipartException;
50 import org.springframework.web.multipart.MultipartFile;
51
52 import static org.junit.Assert.*;
53 import static org.mockito.BDDMockito.*;
54
55
56
57
58
59
60
61
62 public class RequestParamMethodArgumentResolverTests {
63
64 private RequestParamMethodArgumentResolver resolver;
65
66 private MethodParameter paramNamedDefaultValueString;
67 private MethodParameter paramNamedStringArray;
68 private MethodParameter paramNamedMap;
69 private MethodParameter paramMultipartFile;
70 private MethodParameter paramMultipartFileList;
71 private MethodParameter paramMultipartFileArray;
72 private MethodParameter paramPart;
73 private MethodParameter paramPartList;
74 private MethodParameter paramPartArray;
75 private MethodParameter paramMap;
76 private MethodParameter paramStringNotAnnot;
77 private MethodParameter paramMultipartFileNotAnnot;
78 private MethodParameter paramMultipartFileListNotAnnot;
79 private MethodParameter paramPartNotAnnot;
80 private MethodParameter paramRequestPartAnnot;
81 private MethodParameter paramRequired;
82 private MethodParameter paramNotRequired;
83 private MethodParameter paramOptional;
84
85 private NativeWebRequest webRequest;
86
87 private MockHttpServletRequest request;
88
89 @Before
90 public void setUp() throws Exception {
91 resolver = new RequestParamMethodArgumentResolver(null, true);
92
93 ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
94
95 Method method = getClass().getMethod("params", String.class, String[].class,
96 Map.class, MultipartFile.class, List.class, MultipartFile[].class,
97 Part.class, List.class, Part[].class, Map.class,
98 String.class, MultipartFile.class, List.class, Part.class,
99 MultipartFile.class, String.class, String.class, Optional.class);
100
101 paramNamedDefaultValueString = new MethodParameter(method, 0);
102 paramNamedStringArray = new MethodParameter(method, 1);
103 paramNamedMap = new MethodParameter(method, 2);
104 paramMultipartFile = new MethodParameter(method, 3);
105 paramMultipartFileList = new MethodParameter(method, 4);
106 paramMultipartFileArray = new MethodParameter(method, 5);
107 paramPart = new MethodParameter(method, 6);
108 paramPartList = new MethodParameter(method, 7);
109 paramPartArray = new MethodParameter(method, 8);
110 paramMap = new MethodParameter(method, 9);
111 paramStringNotAnnot = new MethodParameter(method, 10);
112 paramStringNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
113 paramMultipartFileNotAnnot = new MethodParameter(method, 11);
114 paramMultipartFileNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
115 paramMultipartFileListNotAnnot = new MethodParameter(method, 12);
116 paramMultipartFileListNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
117 paramPartNotAnnot = new MethodParameter(method, 13);
118 paramPartNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
119 paramRequestPartAnnot = new MethodParameter(method, 14);
120 paramRequired = new MethodParameter(method, 15);
121 paramNotRequired = new MethodParameter(method, 16);
122 paramOptional = new MethodParameter(method, 17);
123
124 request = new MockHttpServletRequest();
125 webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
126 }
127
128 @Test
129 public void supportsParameter() {
130 resolver = new RequestParamMethodArgumentResolver(null, true);
131 assertTrue("String parameter not supported", resolver.supportsParameter(paramNamedDefaultValueString));
132 assertTrue("String array parameter not supported", resolver.supportsParameter(paramNamedStringArray));
133 assertTrue("Named map not parameter supported", resolver.supportsParameter(paramNamedMap));
134 assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFile));
135 assertTrue("List<MultipartFile> parameter not supported", resolver.supportsParameter(paramMultipartFileList));
136 assertTrue("MultipartFile[] parameter not supported", resolver.supportsParameter(paramMultipartFileArray));
137 assertTrue("Part parameter not supported", resolver.supportsParameter(paramPart));
138 assertTrue("List<Part> parameter not supported", resolver.supportsParameter(paramPartList));
139 assertTrue("Part[] parameter not supported", resolver.supportsParameter(paramPartArray));
140 assertFalse("non-@RequestParam parameter supported", resolver.supportsParameter(paramMap));
141 assertTrue("Simple type params supported w/o annotations", resolver.supportsParameter(paramStringNotAnnot));
142 assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFileNotAnnot));
143 assertTrue("Part parameter not supported", resolver.supportsParameter(paramPartNotAnnot));
144
145 resolver = new RequestParamMethodArgumentResolver(null, false);
146 assertFalse(resolver.supportsParameter(paramStringNotAnnot));
147 assertFalse(resolver.supportsParameter(paramRequestPartAnnot));
148 }
149
150 @Test
151 public void resolveString() throws Exception {
152 String expected = "foo";
153 request.addParameter("name", expected);
154
155 Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
156
157 assertTrue(result instanceof String);
158 assertEquals("Invalid result", expected, result);
159 }
160
161 @Test
162 public void resolveStringArray() throws Exception {
163 String[] expected = new String[]{"foo", "bar"};
164 request.addParameter("name", expected);
165
166 Object result = resolver.resolveArgument(paramNamedStringArray, null, webRequest, null);
167
168 assertTrue(result instanceof String[]);
169 assertArrayEquals("Invalid result", expected, (String[]) result);
170 }
171
172 @Test
173 public void resolveMultipartFile() throws Exception {
174 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
175 MultipartFile expected = new MockMultipartFile("mfile", "Hello World".getBytes());
176 request.addFile(expected);
177 webRequest = new ServletWebRequest(request);
178
179 Object result = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
180
181 assertTrue(result instanceof MultipartFile);
182 assertEquals("Invalid result", expected, result);
183 }
184
185 @Test
186 public void resolveMultipartFileList() throws Exception {
187 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
188 MultipartFile expected1 = new MockMultipartFile("mfilelist", "Hello World 1".getBytes());
189 MultipartFile expected2 = new MockMultipartFile("mfilelist", "Hello World 2".getBytes());
190 request.addFile(expected1);
191 request.addFile(expected2);
192 webRequest = new ServletWebRequest(request);
193
194 Object result = resolver.resolveArgument(paramMultipartFileList, null, webRequest, null);
195
196 assertTrue(result instanceof List);
197 assertEquals(Arrays.asList(expected1, expected2), result);
198 }
199
200 @Test
201 public void resolveMultipartFileArray() throws Exception {
202 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
203 MultipartFile expected1 = new MockMultipartFile("mfilearray", "Hello World 1".getBytes());
204 MultipartFile expected2 = new MockMultipartFile("mfilearray", "Hello World 2".getBytes());
205 request.addFile(expected1);
206 request.addFile(expected2);
207 webRequest = new ServletWebRequest(request);
208
209 Object result = resolver.resolveArgument(paramMultipartFileArray, null, webRequest, null);
210
211 assertTrue(result instanceof MultipartFile[]);
212 MultipartFile[] parts = (MultipartFile[]) result;
213 assertEquals(parts[0], expected1);
214 assertEquals(parts[1], expected2);
215 }
216
217 @Test
218 public void resolvePart() throws Exception {
219 MockHttpServletRequest request = new MockHttpServletRequest();
220 MockPart expected = new MockPart("pfile", "Hello World".getBytes());
221 request.setMethod("POST");
222 request.setContentType("multipart/form-data");
223 request.addPart(expected);
224 webRequest = new ServletWebRequest(request);
225
226 Object result = resolver.resolveArgument(paramPart, null, webRequest, null);
227
228 assertTrue(result instanceof Part);
229 assertEquals("Invalid result", expected, result);
230 }
231
232 @Test
233 public void resolvePartList() throws Exception {
234 MockHttpServletRequest request = new MockHttpServletRequest();
235 MockPart expected1 = new MockPart("pfilelist", "Hello World 1".getBytes());
236 MockPart expected2 = new MockPart("pfilelist", "Hello World 2".getBytes());
237 request.setMethod("POST");
238 request.setContentType("multipart/form-data");
239 request.addPart(expected1);
240 request.addPart(expected2);
241 webRequest = new ServletWebRequest(request);
242
243 Object result = resolver.resolveArgument(paramPartList, null, webRequest, null);
244
245 assertTrue(result instanceof List);
246 assertEquals(Arrays.asList(expected1, expected2), result);
247 }
248
249 @Test
250 public void resolvePartArray() throws Exception {
251 MockHttpServletRequest request = new MockHttpServletRequest();
252 MockPart expected1 = new MockPart("pfilearray", "Hello World 1".getBytes());
253 MockPart expected2 = new MockPart("pfilearray", "Hello World 2".getBytes());
254 request.setMethod("POST");
255 request.setContentType("multipart/form-data");
256 request.addPart(expected1);
257 request.addPart(expected2);
258 webRequest = new ServletWebRequest(request);
259
260 Object result = resolver.resolveArgument(paramPartArray, null, webRequest, null);
261
262 assertTrue(result instanceof Part[]);
263 Part[] parts = (Part[]) result;
264 assertEquals(parts[0], expected1);
265 assertEquals(parts[1], expected2);
266 }
267
268 @Test
269 public void resolveMultipartFileNotAnnot() throws Exception {
270 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
271 MultipartFile expected = new MockMultipartFile("multipartFileNotAnnot", "Hello World".getBytes());
272 request.addFile(expected);
273 webRequest = new ServletWebRequest(request);
274
275 Object result = resolver.resolveArgument(paramMultipartFileNotAnnot, null, webRequest, null);
276
277 assertTrue(result instanceof MultipartFile);
278 assertEquals("Invalid result", expected, result);
279 }
280
281 @Test
282 public void resolveMultipartFileListNotAnnotated() throws Exception {
283 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
284 MultipartFile expected1 = new MockMultipartFile("multipartFileList", "Hello World 1".getBytes());
285 MultipartFile expected2 = new MockMultipartFile("multipartFileList", "Hello World 2".getBytes());
286 request.addFile(expected1);
287 request.addFile(expected2);
288 webRequest = new ServletWebRequest(request);
289
290 Object result = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null);
291
292 assertTrue(result instanceof List);
293 assertEquals(Arrays.asList(expected1, expected2), result);
294 }
295
296 @Test(expected = MultipartException.class)
297 public void isMultipartRequest() throws Exception {
298 resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
299 fail("Expected exception: request is not a multipart request");
300 }
301
302
303
304 @Test
305 public void isMultipartRequestHttpPut() throws Exception {
306 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
307 MultipartFile expected = new MockMultipartFile("multipartFileList", "Hello World".getBytes());
308 request.addFile(expected);
309 request.setMethod("PUT");
310 webRequest = new ServletWebRequest(request);
311
312 Object actual = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null);
313
314 assertTrue(actual instanceof List);
315 assertEquals(expected, ((List<?>) actual).get(0));
316 }
317
318 @Test(expected = IllegalArgumentException.class)
319 public void missingMultipartFile() throws Exception {
320 request.setMethod("POST");
321 request.setContentType("multipart/form-data");
322 resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
323 fail("Expected exception: request is not MultiPartHttpServletRequest but param is MultipartFile");
324 }
325
326 @Test
327 public void resolvePartNotAnnot() throws Exception {
328 MockPart expected = new MockPart("part", "Hello World".getBytes());
329 MockHttpServletRequest request = new MockHttpServletRequest();
330 request.setMethod("POST");
331 request.setContentType("multipart/form-data");
332 request.addPart(expected);
333 webRequest = new ServletWebRequest(request);
334
335 Object result = resolver.resolveArgument(paramPartNotAnnot, null, webRequest, null);
336
337 assertTrue(result instanceof Part);
338 assertEquals("Invalid result", expected, result);
339 }
340
341 @Test
342 public void resolveDefaultValue() throws Exception {
343 Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
344
345 assertTrue(result instanceof String);
346 assertEquals("Invalid result", "bar", result);
347 }
348
349 @Test(expected = MissingServletRequestParameterException.class)
350 public void missingRequestParam() throws Exception {
351 resolver.resolveArgument(paramNamedStringArray, null, webRequest, null);
352 fail("Expected exception");
353 }
354
355
356
357 @Test
358 public void missingRequestParamEmptyValueConvertedToNull() throws Exception {
359
360 WebDataBinder binder = new WebRequestDataBinder(null);
361 binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
362
363 WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
364 given(binderFactory.createBinder(webRequest, null, "stringNotAnnot")).willReturn(binder);
365
366 this.request.addParameter("stringNotAnnot", "");
367
368 Object arg = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, binderFactory);
369
370 assertNull(arg);
371 }
372
373 @Test
374 public void missingRequestParamEmptyValueNotRequired() throws Exception {
375
376 WebDataBinder binder = new WebRequestDataBinder(null);
377 binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
378
379 WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
380 given(binderFactory.createBinder(webRequest, null, "name")).willReturn(binder);
381
382 this.request.addParameter("name", "");
383
384 Object arg = resolver.resolveArgument(paramNotRequired, null, webRequest, binderFactory);
385
386 assertNull(arg);
387 }
388
389 @Test
390 public void resolveSimpleTypeParam() throws Exception {
391 request.setParameter("stringNotAnnot", "plainValue");
392 Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null);
393
394 assertTrue(result instanceof String);
395 assertEquals("plainValue", result);
396 }
397
398
399
400 @Test
401 public void resolveSimpleTypeParamToNull() throws Exception {
402 Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null);
403 assertNull(result);
404 }
405
406
407
408 @Test
409 public void resolveEmptyValueToDefault() throws Exception {
410 this.request.addParameter("name", "");
411 Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
412 assertEquals("bar", result);
413 }
414
415 @Test
416 public void resolveEmptyValueWithoutDefault() throws Exception {
417 this.request.addParameter("stringNotAnnot", "");
418 Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null);
419 assertEquals("", result);
420 }
421
422 @Test
423 public void resolveEmptyValueRequiredWithoutDefault() throws Exception {
424 this.request.addParameter("name", "");
425 Object result = resolver.resolveArgument(paramRequired, null, webRequest, null);
426 assertEquals("", result);
427 }
428
429 @Test
430 public void resolveOptional() throws Exception {
431 ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
432 initializer.setConversionService(new DefaultConversionService());
433 WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
434
435 Object result = resolver.resolveArgument(paramOptional, null, webRequest, binderFactory);
436 assertEquals(Optional.class, result.getClass());
437 assertEquals(Optional.empty(), result);
438
439 this.request.addParameter("name", "123");
440 result = resolver.resolveArgument(paramOptional, null, webRequest, binderFactory);
441 assertEquals(Optional.class, result.getClass());
442 assertEquals(123, ((Optional) result).get());
443 }
444
445
446 public void params(@RequestParam(value = "name", defaultValue = "bar") String param1,
447 @RequestParam("name") String[] param2,
448 @RequestParam("name") Map<?, ?> param3,
449 @RequestParam(value = "mfile") MultipartFile param4,
450 @RequestParam(value = "mfilelist") List<MultipartFile> param5,
451 @RequestParam(value = "mfilearray") MultipartFile[] param6,
452 @RequestParam(value = "pfile") Part param7,
453 @RequestParam(value = "pfilelist") List<Part> param8,
454 @RequestParam(value = "pfilearray") Part[] param9,
455 @RequestParam Map<?, ?> param10,
456 String stringNotAnnot,
457 MultipartFile multipartFileNotAnnot,
458 List<MultipartFile> multipartFileList,
459 Part part,
460 @RequestPart MultipartFile requestPartAnnot,
461 @RequestParam(value = "name") String paramRequired,
462 @RequestParam(value = "name", required=false) String paramNotRequired,
463 @RequestParam(value = "name") Optional<Integer> paramOptional) {
464 }
465
466 }