18
18
import org .junit .Before ;
19
19
import org .junit .Test ;
20
20
21
+ import org .springframework .beans .Mergeable ;
21
22
import org .springframework .http .MediaType ;
22
23
import org .springframework .mock .web .MockHttpServletRequest ;
23
24
import org .springframework .mock .web .MockServletContext ;
24
25
import org .springframework .security .test .web .servlet .request .SecurityMockMvcRequestPostProcessors .CsrfRequestPostProcessor ;
25
26
import org .springframework .security .web .csrf .CsrfToken ;
27
+ import org .springframework .test .web .servlet .RequestBuilder ;
28
+ import org .springframework .test .web .servlet .SmartRequestBuilder ;
29
+ import org .springframework .test .web .servlet .request .ConfigurableSmartRequestBuilder ;
30
+ import org .springframework .test .web .servlet .request .MockMvcRequestBuilders ;
31
+ import org .springframework .test .web .servlet .request .RequestPostProcessor ;
32
+ import org .springframework .test .web .servlet .setup .AbstractMockMvcBuilder ;
33
+ import org .springframework .test .web .servlet .setup .DefaultMockMvcBuilder ;
34
+ import org .springframework .util .Assert ;
35
+ import org .springframework .web .context .support .GenericWebApplicationContext ;
36
+
37
+ import javax .servlet .ServletContext ;
26
38
27
39
import static org .assertj .core .api .Assertions .assertThat ;
28
40
import static org .springframework .security .test .web .servlet .request .SecurityMockMvcRequestBuilders .formLogin ;
@@ -82,6 +94,46 @@ public void customWithUriVars() {
82
94
assertThat (request .getRequestURI ()).isEqualTo ("/uri-login/val1/val2" );
83
95
}
84
96
97
+ @ Test
98
+ public void postProcessorsAreMergedDuringMockMvcPerform () throws Exception {
99
+
100
+ RequestBuilder requestBuilder = formLogin ()
101
+ .user ("my-user" )
102
+ .password ("my-password" )
103
+ .loginProcessingUrl ("/my-path" );
104
+
105
+ // spring-restdocs project creates request postprocessors using this hook:
106
+ // org.springframework.test.web.servlet.setup.MockMvcConfigurer.beforeMockMvcCreated
107
+ // The postprocessors are bound to the defaultRequestBuilder instance (with urlTemplate "/") here:
108
+ // org.springframework.test.web.servlet.setup.AbstractMockMvcBuilder.build
109
+ // The bind happens only if the default builder implements the ConfigurableSmartRequestBuilder interface.
110
+
111
+ RequestBuilder defaultRequestBuilder = MockMvcRequestBuilders .get ("/" );
112
+ if (defaultRequestBuilder instanceof ConfigurableSmartRequestBuilder ) {
113
+ ((ConfigurableSmartRequestBuilder ) defaultRequestBuilder ).with (new MockPostProcessor ());
114
+ }
115
+
116
+ // In the following method:
117
+ // org.springframework.test.web.servlet.MockMvc.perform
118
+ // the RequestBuilder is normally merged with the defaultRequestBuilder, so the spring-restdocs postprocessor
119
+ // can be executed and it can generate nice documentations.
120
+ // The problem is, that this merge happens only if the RequestBuilder implements Mergeable interface.
121
+
122
+ if (defaultRequestBuilder != null && requestBuilder instanceof Mergeable ) {
123
+ requestBuilder = (RequestBuilder ) ((Mergeable ) requestBuilder ).merge (defaultRequestBuilder );
124
+ }
125
+
126
+ // Currently, none of SecurityMockMvcRequestBuilders implements this interface.
127
+ // They should implement ConfigurableSmartRequestBuilder interface also to be able to take over
128
+ // the postprocessors (and execute them).
129
+
130
+ MockHttpServletRequest request = requestBuilder .buildRequest (this .servletContext );
131
+
132
+ Assert .isInstanceOf (ConfigurableSmartRequestBuilder .class , requestBuilder );
133
+ Assert .isTrue (request .equals (((SmartRequestBuilder ) requestBuilder ).postProcessRequest (request )),
134
+ "Postprocessing failed." );
135
+ }
136
+
85
137
// gh-3920
86
138
@ Test
87
139
public void usesAcceptMediaForContentNegotiation () {
@@ -91,4 +143,12 @@ public void usesAcceptMediaForContentNegotiation() {
91
143
assertThat (request .getHeader ("Accept" ))
92
144
.isEqualTo (MediaType .APPLICATION_FORM_URLENCODED_VALUE );
93
145
}
146
+
147
+ private class MockPostProcessor implements RequestPostProcessor {
148
+
149
+ @ Override
150
+ public MockHttpServletRequest postProcessRequest ( MockHttpServletRequest request ) {
151
+ return request ;
152
+ }
153
+ }
94
154
}
0 commit comments