23
23
import java .util .function .Function ;
24
24
import java .util .stream .StreamSupport ;
25
25
26
+ import org .assertj .core .api .AssertProvider ;
27
+
28
+ import org .springframework .http .HttpMethod ;
26
29
import org .springframework .http .MediaType ;
27
30
import org .springframework .http .converter .GenericHttpMessageConverter ;
28
31
import org .springframework .http .converter .HttpMessageConverter ;
29
32
import org .springframework .lang .Nullable ;
33
+ import org .springframework .mock .web .MockHttpServletRequest ;
30
34
import org .springframework .test .web .servlet .MockMvc ;
31
35
import org .springframework .test .web .servlet .MvcResult ;
32
36
import org .springframework .test .web .servlet .RequestBuilder ;
37
+ import org .springframework .test .web .servlet .request .AbstractMockHttpServletRequestBuilder ;
33
38
import org .springframework .test .web .servlet .request .MockMvcRequestBuilders ;
34
39
import org .springframework .test .web .servlet .setup .DefaultMockMvcBuilder ;
35
40
import org .springframework .test .web .servlet .setup .MockMvcBuilders ;
58
63
* MockMvcTester mvc = MockMvcTester.of(new PersonController());
59
64
* </code></pre>
60
65
*
61
- * <p>Once a tester instance is available, you can perform requests in a similar
62
- * fashion as with {@link MockMvc}, and wrapping the result in
63
- * {@code assertThat()} provides access to assertions. For instance:
66
+ * <p>Simple, single-statement assertions can be done wrapping the request
67
+ * builder in {@code assertThat()} provides access to assertions. For instance:
64
68
* <pre><code class="java">
65
69
* // perform a GET on /hi and assert the response body is equal to Hello
70
+ * assertThat(mvc.get().uri("/hi")).hasStatusOk().hasBodyTextEqualTo("Hello");
71
+ * </code></pre>
72
+ *
73
+ *<p>For more complex scenarios the {@linkplain MvcTestResult result} of the
74
+ * exchange can be assigned in a variable to run multiple assertions:
75
+ * <pre><code class="java">
76
+ * // perform a POST on /save and assert the response body is empty
77
+ * MvcTestResult result = mvc.post().uri("/save").exchange();
78
+ * assertThat(result).hasStatus(HttpStatus.CREATED);
79
+ * assertThat(result).body().isEmpty();
80
+ * </code></pre>
81
+ *
82
+ * <p>You can also perform requests using the static builders approach that
83
+ * {@link MockMvc} uses. For instance:<pre><code class="java">
84
+ * // perform a GET on /hi and assert the response body is equal to Hello
66
85
* assertThat(mvc.perform(get("/hi")))
67
86
* .hasStatusOk().hasBodyTextEqualTo("Hello");
68
87
* </code></pre>
74
93
* which allows you to assert that a request failed unexpectedly:
75
94
* <pre><code class="java">
76
95
* // perform a GET on /boom and assert the message for the the unresolved exception
77
- * assertThat(mvc.perform(get("/boom")))
78
- * .hasUnresolvedException())
96
+ * assertThat(mvc.get().uri("/boom")).hasUnresolvedException())
79
97
* .withMessage("Test exception");
80
98
* </code></pre>
81
99
*
82
- * <p>{@link MockMvcTester} can be configured with a list of
100
+ * <p>{@code MockMvcTester} can be configured with a list of
83
101
* {@linkplain HttpMessageConverter message converters} to allow the response
84
102
* body to be deserialized, rather than asserting on the raw values.
85
103
*
@@ -104,18 +122,17 @@ private MockMvcTester(MockMvc mockMvc, @Nullable GenericHttpMessageConverter<Obj
104
122
}
105
123
106
124
/**
107
- * Create a {@link MockMvcTester} instance that delegates to the given
108
- * {@link MockMvc} instance.
125
+ * Create an instance that delegates to the given {@link MockMvc} instance.
109
126
* @param mockMvc the MockMvc instance to delegate calls to
110
127
*/
111
128
public static MockMvcTester create (MockMvc mockMvc ) {
112
129
return new MockMvcTester (mockMvc , null );
113
130
}
114
131
115
132
/**
116
- * Create an {@link MockMvcTester} instance using the given, fully
117
- * initialized (i.e., <em>refreshed</em>) {@link WebApplicationContext}. The
118
- * given {@code customizations} are applied to the {@link DefaultMockMvcBuilder}
133
+ * Create an instance using the given, fully initialized (i.e.,
134
+ * <em>refreshed</em>) {@link WebApplicationContext}. The given
135
+ * {@code customizations} are applied to the {@link DefaultMockMvcBuilder}
119
136
* that ultimately creates the underlying {@link MockMvc} instance.
120
137
* <p>If no further customization of the underlying {@link MockMvc} instance
121
138
* is required, use {@link #from(WebApplicationContext)}.
@@ -134,8 +151,8 @@ public static MockMvcTester from(WebApplicationContext applicationContext,
134
151
}
135
152
136
153
/**
137
- * Shortcut to create an {@link MockMvcTester} instance using the given,
138
- * fully initialized (i.e., <em>refreshed</em>) {@link WebApplicationContext}.
154
+ * Shortcut to create an instance using the given fully initialized (i.e. ,
155
+ * <em>refreshed</em>) {@link WebApplicationContext}.
139
156
* <p>Consider using {@link #from(WebApplicationContext, Function)} if
140
157
* further customization of the underlying {@link MockMvc} instance is
141
158
* required.
@@ -148,9 +165,8 @@ public static MockMvcTester from(WebApplicationContext applicationContext) {
148
165
}
149
166
150
167
/**
151
- * Create an {@link MockMvcTester} instance by registering one or more
152
- * {@code @Controller} instances and configuring Spring MVC infrastructure
153
- * programmatically.
168
+ * Create an instance by registering one or more {@code @Controller} instances
169
+ * and configuring Spring MVC infrastructure programmatically.
154
170
* <p>This allows full control over the instantiation and initialization of
155
171
* controllers and their dependencies, similar to plain unit tests while
156
172
* also making it possible to test one controller at a time.
@@ -170,8 +186,8 @@ public static MockMvcTester of(Collection<?> controllers,
170
186
}
171
187
172
188
/**
173
- * Shortcut to create an {@link MockMvcTester} instance by registering one
174
- * or more {@code @Controller} instances.
189
+ * Shortcut to create an instance by registering one or more {@code @Controller}
190
+ * instances.
175
191
* <p>The minimum infrastructure required by the
176
192
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}
177
193
* to serve requests with annotated controllers is created. Consider using
@@ -187,8 +203,8 @@ public static MockMvcTester of(Object... controllers) {
187
203
}
188
204
189
205
/**
190
- * Return a new {@link MockMvcTester} instance using the specified
191
- * {@linkplain HttpMessageConverter message converters}.
206
+ * Return a new instance using the specified {@linkplain HttpMessageConverter
207
+ * message converters}.
192
208
* <p>If none are specified, only basic assertions on the response body can
193
209
* be performed. Consider registering a suitable JSON converter for asserting
194
210
* against JSON data structures.
@@ -200,8 +216,105 @@ public MockMvcTester withHttpMessageConverters(Iterable<HttpMessageConverter<?>>
200
216
}
201
217
202
218
/**
203
- * Perform a request and return a {@link MvcTestResult result} that can be
204
- * used with standard {@link org.assertj.core.api.Assertions AssertJ} assertions.
219
+ * Prepare an HTTP GET request.
220
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
221
+ * assertions on the result. For multi-statements assertions, use
222
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
223
+ * result.
224
+ * @return a request builder for specifying the target URI
225
+ */
226
+ public MockMvcRequestBuilder get () {
227
+ return method (HttpMethod .GET );
228
+ }
229
+
230
+ /**
231
+ * Prepare an HTTP HEAD request.
232
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
233
+ * assertions on the result. For multi-statements assertions, use
234
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
235
+ * result.
236
+ * @return a request builder for specifying the target URI
237
+ */
238
+ public MockMvcRequestBuilder head () {
239
+ return method (HttpMethod .HEAD );
240
+ }
241
+
242
+ /**
243
+ * Prepare an HTTP POST request.
244
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
245
+ * assertions on the result. For multi-statements assertions, use
246
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
247
+ * result.
248
+ * @return a request builder for specifying the target URI
249
+ */
250
+ public MockMvcRequestBuilder post () {
251
+ return method (HttpMethod .POST );
252
+ }
253
+
254
+ /**
255
+ * Prepare an HTTP PUT request.
256
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
257
+ * assertions on the result. For multi-statements assertions, use
258
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
259
+ * result.
260
+ * @return a request builder for specifying the target URI
261
+ */
262
+ public MockMvcRequestBuilder put () {
263
+ return method (HttpMethod .PUT );
264
+ }
265
+
266
+ /**
267
+ * Prepare an HTTP PATCH request.
268
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
269
+ * assertions on the result. For multi-statements assertions, use
270
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
271
+ * result.
272
+ * @return a request builder for specifying the target URI
273
+ */
274
+ public MockMvcRequestBuilder patch () {
275
+ return method (HttpMethod .PATCH );
276
+ }
277
+
278
+ /**
279
+ * Prepare an HTTP DELETE request.
280
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
281
+ * assertions on the result. For multi-statements assertions, use
282
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
283
+ * result.
284
+ * @return a request builder for specifying the target URI
285
+ */
286
+ public MockMvcRequestBuilder delete () {
287
+ return method (HttpMethod .DELETE );
288
+ }
289
+
290
+ /**
291
+ * Prepare an HTTP OPTIONS request.
292
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
293
+ * assertions on the result. For multi-statements assertions, use
294
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
295
+ * result.
296
+ * @return a request builder for specifying the target URI
297
+ */
298
+ public MockMvcRequestBuilder options () {
299
+ return method (HttpMethod .OPTIONS );
300
+ }
301
+
302
+ /**
303
+ * Prepare a request for the specified {@code HttpMethod}.
304
+ * <p>The returned builder can be wrapped in {@code assertThat} to enable
305
+ * assertions on the result. For multi-statements assertions, use
306
+ * {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
307
+ * result.
308
+ * @return a request builder for specifying the target URI
309
+ */
310
+ public MockMvcRequestBuilder method (HttpMethod method ) {
311
+ return new MockMvcRequestBuilder (method );
312
+ }
313
+
314
+ /**
315
+ * Perform a request using {@link MockMvcRequestBuilders} and return a
316
+ * {@link MvcTestResult result} that can be used with standard
317
+ * {@link org.assertj.core.api.Assertions AssertJ} assertions.
205
318
* <p>Use static methods of {@link MockMvcRequestBuilders} to prepare the
206
319
* request, wrapping the invocation in {@code assertThat}. The following
207
320
* asserts that a {@linkplain MockMvcRequestBuilders#get(URI) GET} request
@@ -226,6 +339,8 @@ public MockMvcTester withHttpMessageConverters(Iterable<HttpMessageConverter<?>>
226
339
* {@link org.springframework.test.web.servlet.request.MockMvcRequestBuilders}
227
340
* @return an {@link MvcTestResult} to be wrapped in {@code assertThat}
228
341
* @see MockMvc#perform(RequestBuilder)
342
+ * @see #get()
343
+ * @see #post()
229
344
*/
230
345
public MvcTestResult perform (RequestBuilder requestBuilder ) {
231
346
Object result = getMvcResultOrFailure (requestBuilder );
@@ -259,4 +374,25 @@ private GenericHttpMessageConverter<Object> findJsonMessageConverter(
259
374
.findFirst ().orElse (null );
260
375
}
261
376
377
+
378
+ /**
379
+ * A builder for {@link MockHttpServletRequest} that supports AssertJ.
380
+ */
381
+ public final class MockMvcRequestBuilder extends AbstractMockHttpServletRequestBuilder <MockMvcRequestBuilder >
382
+ implements AssertProvider <MvcTestResultAssert > {
383
+
384
+ private MockMvcRequestBuilder (HttpMethod httpMethod ) {
385
+ super (httpMethod );
386
+ }
387
+
388
+ public MvcTestResult exchange () {
389
+ return perform (this );
390
+ }
391
+
392
+ @ Override
393
+ public MvcTestResultAssert assertThat () {
394
+ return new MvcTestResultAssert (exchange (), MockMvcTester .this .jsonMessageConverter );
395
+ }
396
+ }
397
+
262
398
}
0 commit comments