Skip to content

Commit 21aee8e

Browse files
schosinf-lopes
authored andcommitted
Add support for adding form params via with(RequestPostProcessor). (#9)
* Set next development version: 2.2.0-SNAPSHOT * Add Eclipse / STS specific files/folders to .gitignore * Add support for adding form params via with(RequestPostProcessor) * Create `FormRequestPostProcessor` and add POST,PUT,GET smoke tests * Document usage with FormRequestPostProcessor
1 parent f40fc2c commit 21aee8e

File tree

6 files changed

+283
-12
lines changed

6 files changed

+283
-12
lines changed

.gitignore

+12
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ hs_err_pid*
3838
# IntelliJ
3939
/out/
4040

41+
### Eclipse / STS ###
42+
.apt_generated
43+
.classpath
44+
.factorypath
45+
.externalToolBuilders
46+
.project
47+
.settings
48+
.springBeans
49+
.eclipse-pmd
50+
/.temp-*
51+
bin
52+
4153
# mpeltonen/sbt-idea plugin
4254
.idea_modules/
4355

README.md

+22-4
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,28 @@ public void testSimpleFields() throws Exception {
4141

4242
Usage with MockMvc:
4343
```
44-
mockMvc.perform(MockMvcRequestBuilderUtils.postForm("/users", new AddUserForm("John", "Doe", null, null)))
45-
.andExpect(MockMvcResultMatchers.status().isFound())
46-
.andExpect(MockMvcResultMatchers.redirectedUrl("/users"))
47-
.andExpect(MockMvcResultMatchers.flash().attribute("message", "success"));
44+
final AddUserForm addUserForm = new AddUserForm("John", "Doe", null, new Address(1, "Street", 5222, "New York")));
45+
46+
mockMvc.perform(MockMvcRequestBuilderUtils.postForm("/users", addUserForm))
47+
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
48+
```
49+
50+
Using `with()` syntax (`FormRequestPostProcessor`):
51+
52+
```
53+
final AddUserForm addUserForm = new AddUserForm("John", "Doe", null, new Address(1, "Street", 5222, "New York")));
54+
55+
// POST
56+
mockMvc.perform(post("/users").with(MockMvcRequestBuilderUtils.form(addUserForm)))
57+
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
58+
59+
// GET
60+
mockMvc.perform(get("/users").with(MockMvcRequestBuilderUtils.form(addUserForm)))
61+
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
62+
63+
// PUT
64+
mockMvc.perform(put("/users").with(MockMvcRequestBuilderUtils.form(addUserForm)))
65+
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
4866
```
4967

5068
### Register property editor(s)

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>io.florianlopes</groupId>
88
<artifactId>spring-mvc-test-utils</artifactId>
9-
<version>2.1.0</version>
9+
<version>2.2.0-SNAPSHOT</version>
1010
<packaging>jar</packaging>
1111

1212
<name>spring-mvc-test-utils</name>

src/main/java/io/florianlopes/spring/test/web/servlet/request/MockMvcRequestBuilderUtils.java

+28
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
import org.springframework.beans.PropertyEditorRegistrySupport;
1919
import org.springframework.beans.SimpleTypeConverter;
2020
import org.springframework.http.MediaType;
21+
import org.springframework.mock.web.MockHttpServletRequest;
2122
import org.springframework.test.util.ReflectionTestUtils;
2223
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
2324
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
25+
import org.springframework.test.web.servlet.request.RequestPostProcessor;
2426
import org.springframework.util.ClassUtils;
2527
import org.springframework.util.CollectionUtils;
2628

@@ -50,6 +52,10 @@ public static void registerPropertyEditor(Class type, PropertyEditor propertyEdi
5052
propertyEditorRegistry.registerCustomEditor(type, propertyEditor);
5153
}
5254

55+
public static FormRequestPostProcessor form(Object form) {
56+
return new FormRequestPostProcessor(form);
57+
}
58+
5359
/**
5460
* Post a form to the given url.
5561
* All non-null form fields will be added as HTTP request parameters using POST method
@@ -219,4 +225,26 @@ private static boolean isIterable(Class fieldClass) {
219225
private static boolean isMap(Class<?> type) {
220226
return Map.class.isAssignableFrom(type);
221227
}
228+
229+
/**
230+
* Implementation of {@link RequestPostProcessor} that adds form parameters to the request before execution.
231+
*/
232+
public static class FormRequestPostProcessor implements RequestPostProcessor {
233+
234+
private final Object form;
235+
236+
private FormRequestPostProcessor(Object form) {
237+
this.form = form;
238+
}
239+
240+
@Override
241+
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
242+
final Map<String, String> formFields = getFormFields(form, new TreeMap<>(), StringUtils.EMPTY);
243+
formFields.forEach((path, value) -> {
244+
logger.debug(String.format("Adding form field (%s=%s) to HTTP request parameters", path, value));
245+
request.addParameter(path, value);
246+
});
247+
return request;
248+
}
249+
}
222250
}

src/test/java/io/florianlopes/spring/test/web/servlet/request/MockMvcRequestBuilderUtilsSmokeTests.java

+31-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.florianlopes.spring.test.web.servlet.request;
22

3+
import static io.florianlopes.spring.test.web.servlet.request.MockMvcRequestBuilderUtils.form;
34
import java.math.BigDecimal;
45
import java.math.BigInteger;
56
import java.time.LocalDate;
@@ -13,12 +14,14 @@
1314
import org.junit.Test;
1415
import org.springframework.stereotype.Controller;
1516
import org.springframework.test.web.servlet.MockMvc;
17+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
18+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
19+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
1620
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
1721
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
1822
import org.springframework.validation.BindingResult;
1923
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
2024
import org.springframework.web.bind.annotation.RequestMapping;
21-
import org.springframework.web.bind.annotation.RequestMethod;
2225

2326
/**
2427
* Created by flopes on 15/04/2018.
@@ -34,20 +37,41 @@ public void setUp() {
3437
this.mockMvc = MockMvcBuilders.standaloneSetup(new UserController())
3538
.setValidator(new LocalValidatorFactoryBean())
3639
.build();
40+
41+
MockMvcRequestBuilderUtils.registerPropertyEditor(LocalDate.class, new CustomLocalDatePropertyEditor(DATE_FORMAT_PATTERN));
3742
}
3843

3944
@Test
4045
public void fullTest() throws Exception {
4146
final AddUserForm addUserForm = getCompletedAddUserForm();
4247

43-
MockMvcRequestBuilderUtils.registerPropertyEditor(LocalDate.class, new CustomLocalDatePropertyEditor(DATE_FORMAT_PATTERN));
44-
final LocalDate bachelorDate = LocalDate.now().minusYears(2);
45-
final LocalDate masterDate = LocalDate.now();
46-
addUserForm.setDiplomas(Arrays.asList(new AddUserForm.Diploma("License", bachelorDate), new AddUserForm.Diploma("MSC", masterDate)));
47-
4848
this.mockMvc.perform(MockMvcRequestBuilderUtils.postForm("/users", addUserForm))
4949
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
5050
}
51+
52+
@Test
53+
public void withParamsFullTestGetMethod() throws Exception {
54+
final AddUserForm addUserForm = getCompletedAddUserForm();
55+
56+
this.mockMvc.perform(get("/users").with(form(addUserForm)))
57+
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
58+
}
59+
60+
@Test
61+
public void withParamsFullTestPutMethod() throws Exception {
62+
final AddUserForm addUserForm = getCompletedAddUserForm();
63+
64+
this.mockMvc.perform(put("/users").with(form(addUserForm)))
65+
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
66+
}
67+
68+
@Test
69+
public void withParamsFullTestPostMethod() throws Exception {
70+
final AddUserForm addUserForm = getCompletedAddUserForm();
71+
72+
this.mockMvc.perform(post("/users").with(form(addUserForm)))
73+
.andExpect(MockMvcResultMatchers.model().hasNoErrors());
74+
}
5175

5276
private AddUserForm getCompletedAddUserForm() {
5377
final LocalDate userBirthDate = LocalDate.of(2016, 8, 29);
@@ -81,7 +105,7 @@ private AddUserForm getCompletedAddUserForm() {
81105
@Controller
82106
private class UserController {
83107

84-
@RequestMapping(value = "/users", method = RequestMethod.POST)
108+
@RequestMapping(value = "/users")
85109
public String addUser(@Valid AddUserForm addUserForm, BindingResult bindingResult) {
86110
return StringUtils.EMPTY;
87111
}

src/test/java/io/florianlopes/spring/test/web/servlet/request/MockMvcRequestBuilderUtilsTests.java

+189
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import org.apache.commons.lang3.StringUtils;
1313
import static org.junit.Assert.assertEquals;
1414
import static org.junit.Assert.assertNull;
15+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
16+
1517
import org.junit.Before;
1618
import org.junit.Test;
1719
import org.springframework.beans.propertyeditors.CustomNumberEditor;
@@ -33,6 +35,193 @@ public class MockMvcRequestBuilderUtilsTests {
3335
public void setUp() {
3436
this.servletContext = new MockServletContext();
3537
}
38+
39+
@Test
40+
public void withParamsNullForm() {
41+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
42+
.with(MockMvcRequestBuilderUtils.form(null));
43+
final MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
44+
mockHttpServletRequestBuilder.postProcessRequest(request);
45+
46+
assertEquals(0, request.getParameterMap().size());
47+
}
48+
49+
@Test
50+
public void withParamsNullAndEmptyFields() {
51+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
52+
.with(MockMvcRequestBuilderUtils.form(new AddUserForm("", "", null, null)));
53+
final MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
54+
mockHttpServletRequestBuilder.postProcessRequest(request);
55+
56+
assertEquals(StringUtils.EMPTY, request.getParameter("name"));
57+
assertEquals(StringUtils.EMPTY, request.getParameter("firstName"));
58+
assertNull(request.getParameter("birthDate"));
59+
assertNull(request.getParameter("currentAddress.city"));
60+
}
61+
62+
@Test
63+
public void withParamsSimpleFields() {
64+
final AddUserForm addUserForm = AddUserForm.builder()
65+
.firstName("John").name("Doe")
66+
.currentAddress(new AddUserForm.Address(1, "Street", 5222, "New York"))
67+
.build();
68+
69+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
70+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
71+
final MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
72+
mockHttpServletRequestBuilder.postProcessRequest(request);
73+
74+
assertEquals("John", request.getParameter("firstName"));
75+
assertEquals("New York", request.getParameter("currentAddress.city"));
76+
}
77+
78+
@Test
79+
public void withParamsSimpleCollection() {
80+
final AddUserForm addUserForm = AddUserForm.builder().firstName("John").name("Doe")
81+
.usernames(Arrays.asList("john.doe", "jdoe"))
82+
.build();
83+
84+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
85+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
86+
final MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
87+
mockHttpServletRequestBuilder.postProcessRequest(request);
88+
89+
assertEquals("john.doe", request.getParameter("usernames[0]"));
90+
assertEquals("jdoe", request.getParameter("usernames[1]"));
91+
}
92+
93+
@Test
94+
public void withParamsComplexCollection() {
95+
final AddUserForm addUserForm = AddUserForm.builder().firstName("John").name("Doe").build();
96+
MockMvcRequestBuilderUtils.registerPropertyEditor(LocalDate.class, new CustomLocalDatePropertyEditor(DATE_FORMAT_PATTERN));
97+
final LocalDate bachelorDate = LocalDate.now().minusYears(2);
98+
final LocalDate masterDate = LocalDate.now();
99+
addUserForm.setDiplomas(Arrays.asList(new AddUserForm.Diploma("License", bachelorDate), new AddUserForm.Diploma("MSC", masterDate)));
100+
101+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
102+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
103+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
104+
mockHttpServletRequestBuilder.postProcessRequest(request);
105+
106+
assertEquals("License", request.getParameter("diplomas[0].name"));
107+
assertEquals(bachelorDate.format(DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN)), request.getParameter("diplomas[0].date"));
108+
assertEquals("MSC", request.getParameter("diplomas[1].name"));
109+
assertEquals(masterDate.format(DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN)), request.getParameter("diplomas[1].date"));
110+
}
111+
112+
@Test
113+
public void withParamsSimpleArray() {
114+
final AddUserForm addUserForm = AddUserForm.builder().firstName("John").name("Doe")
115+
.usernamesArray(new String[]{"john.doe", "jdoe"})
116+
.build();
117+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
118+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
119+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
120+
mockHttpServletRequestBuilder.postProcessRequest(request);
121+
122+
assertEquals("john.doe", request.getParameter("usernamesArray[0]"));
123+
assertEquals("jdoe", request.getParameter("usernamesArray[1]"));
124+
}
125+
126+
@Test
127+
public void withParamsComplexArray() {
128+
final AddUserForm addUserForm = AddUserForm.builder().firstName("John").name("Doe")
129+
.usernames(Arrays.asList("john.doe", "jdoe"))
130+
.formerAddresses(new AddUserForm.Address[]{
131+
new AddUserForm.Address(10, "Street", 5222, "Chicago"),
132+
new AddUserForm.Address(20, "Street", 5222, "Washington")
133+
})
134+
.build();
135+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
136+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
137+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
138+
mockHttpServletRequestBuilder.postProcessRequest(request);
139+
140+
assertEquals("john.doe", request.getParameter("usernames[0]"));
141+
assertEquals("jdoe", request.getParameter("usernames[1]"));
142+
}
143+
144+
@Test
145+
public void withParamsEnumField() {
146+
final AddUserForm addUserForm = AddUserForm.builder()
147+
.firstName("John").name("Doe").gender(AddUserForm.Gender.MALE)
148+
.build();
149+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
150+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
151+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
152+
mockHttpServletRequestBuilder.postProcessRequest(request);
153+
154+
assertEquals("MALE", request.getParameter("gender"));
155+
}
156+
157+
@Test
158+
public void withParamsSimpleMapField() {
159+
final Map<String, String> metadatas = new HashMap<>();
160+
metadatas.put("firstName", "John");
161+
metadatas.put("name", "Doe");
162+
metadatas.put("gender", null);
163+
final AddUserForm addUserForm = AddUserForm.builder()
164+
.metadatas(metadatas)
165+
.build();
166+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
167+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
168+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
169+
mockHttpServletRequestBuilder.postProcessRequest(request);
170+
171+
assertEquals("John", request.getParameter("metadatas[firstName]"));
172+
assertEquals("Doe", request.getParameter("metadatas[name]"));
173+
assertEquals("", request.getParameter("metadatas[gender]"));
174+
}
175+
176+
@Test
177+
public void withParamsBigDecimal() {
178+
final AddUserForm addUserForm = AddUserForm.builder()
179+
.identificationNumber(BigDecimal.TEN)
180+
.build();
181+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
182+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
183+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
184+
mockHttpServletRequestBuilder.postProcessRequest(request);
185+
186+
assertEquals("10", request.getParameter("identificationNumber"));
187+
}
188+
189+
@Test
190+
public void withParamsBigInteger() {
191+
final AddUserForm addUserForm = AddUserForm.builder()
192+
.identificationNumberBigInt(BigInteger.TEN)
193+
.build();
194+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
195+
.with(MockMvcRequestBuilderUtils.form(addUserForm));
196+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
197+
mockHttpServletRequestBuilder.postProcessRequest(request);
198+
199+
assertEquals("10", request.getParameter("identificationNumberBigInt"));
200+
}
201+
202+
@Test
203+
public void withParamsRegisterPropertyEditor() {
204+
try {
205+
// Registering a property editor should override default conversion strategy
206+
MockMvcRequestBuilderUtils.registerPropertyEditor(BigInteger.class, new PropertyEditorSupport() {
207+
@Override
208+
public String getAsText() {
209+
return "textValue";
210+
}
211+
});
212+
213+
final AddUserForm build = AddUserForm.builder().identificationNumberBigInt(BigInteger.TEN).build();
214+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = post(POST_FORM_URL)
215+
.with(MockMvcRequestBuilderUtils.form(build));
216+
MockHttpServletRequest request = mockHttpServletRequestBuilder.buildRequest(this.servletContext);
217+
mockHttpServletRequestBuilder.postProcessRequest(request);
218+
219+
assertEquals("textValue", request.getParameter("identificationNumberBigInt"));
220+
} finally {
221+
// Restore original property editor
222+
MockMvcRequestBuilderUtils.registerPropertyEditor(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));
223+
}
224+
}
36225

37226
@Test
38227
public void correctUrl() {

0 commit comments

Comments
 (0)