0
# Web Testing Support
1
2
Spring's web testing support provides MockMvc framework for testing Spring MVC controllers without starting a full HTTP server. It offers fluent API for request building, response assertions, and integrates seamlessly with the TestContext Framework.
3
4
## Capabilities
5
6
### MockMvc
7
8
The main entry point for server-side Spring MVC testing, providing request execution and result assertion capabilities.
9
10
```java { .api }
11
/**
12
* Main entry point for server-side Spring MVC test support.
13
* Provides a fluent API to perform requests and verify results.
14
*/
15
public final class MockMvc {
16
17
/**
18
* Perform a request and return a type that allows chaining further actions,
19
* such as asserting expectations, on the result.
20
* @param requestBuilder used to prepare the request to execute
21
* @return an instance of ResultActions (never null)
22
* @throws Exception if an exception occurs during request execution
23
*/
24
public ResultActions perform(RequestBuilder requestBuilder) throws Exception;
25
}
26
27
/**
28
* Factory class for creating MockMvc instances.
29
*/
30
public final class MockMvcBuilders {
31
32
/**
33
* Build a MockMvc instance using the given WebApplicationContext.
34
* @param context the WebApplicationContext to use
35
* @return a MockMvcBuilder to further configure the MockMvc instance
36
*/
37
public static DefaultMockMvcBuilder webAppContextSetup(WebApplicationContext context);
38
39
/**
40
* Build a MockMvc instance by registering one or more @Controller instances
41
* and configuring Spring MVC infrastructure programmatically.
42
* @param controllers one or more @Controller instances to test
43
* @return a StandaloneMockMvcBuilder to further configure the MockMvc instance
44
*/
45
public static StandaloneMockMvcBuilder standaloneSetup(Object... controllers);
46
47
/**
48
* Build a MockMvc instance using the given RouterFunction.
49
* @param routerFunction the RouterFunction to use
50
* @return a MockMvcBuilder to further configure the MockMvc instance
51
*/
52
public static RouterFunctionMockMvcBuilder routerFunction(RouterFunction<?> routerFunction);
53
}
54
```
55
56
### Request Building
57
58
Factory and builder classes for creating HTTP requests in tests.
59
60
```java { .api }
61
/**
62
* Static factory methods for RequestBuilder instances that create various types of HTTP requests.
63
*/
64
public abstract class MockMvcRequestBuilders {
65
66
/**
67
* Create a MockHttpServletRequestBuilder for a GET request.
68
* @param urlTemplate a URL template; the resulting URL will be encoded
69
* @param uriVariables zero or more URI variables
70
* @return the request builder
71
*/
72
public static MockHttpServletRequestBuilder get(String urlTemplate, Object... uriVariables);
73
74
/**
75
* Create a MockHttpServletRequestBuilder for a POST request.
76
* @param urlTemplate a URL template; the resulting URL will be encoded
77
* @param uriVariables zero or more URI variables
78
* @return the request builder
79
*/
80
public static MockHttpServletRequestBuilder post(String urlTemplate, Object... uriVariables);
81
82
/**
83
* Create a MockHttpServletRequestBuilder for a PUT request.
84
* @param urlTemplate a URL template; the resulting URL will be encoded
85
* @param uriVariables zero or more URI variables
86
* @return the request builder
87
*/
88
public static MockHttpServletRequestBuilder put(String urlTemplate, Object... uriVariables);
89
90
/**
91
* Create a MockHttpServletRequestBuilder for a PATCH request.
92
* @param urlTemplate a URL template; the resulting URL will be encoded
93
* @param uriVariables zero or more URI variables
94
* @return the request builder
95
*/
96
public static MockHttpServletRequestBuilder patch(String urlTemplate, Object... uriVariables);
97
98
/**
99
* Create a MockHttpServletRequestBuilder for a DELETE request.
100
* @param urlTemplate a URL template; the resulting URL will be encoded
101
* @param uriVariables zero or more URI variables
102
* @return the request builder
103
*/
104
public static MockHttpServletRequestBuilder delete(String urlTemplate, Object... uriVariables);
105
106
/**
107
* Create a MockHttpServletRequestBuilder for a HEAD request.
108
* @param urlTemplate a URL template; the resulting URL will be encoded
109
* @param uriVariables zero or more URI variables
110
* @return the request builder
111
*/
112
public static MockHttpServletRequestBuilder head(String urlTemplate, Object... uriVariables);
113
114
/**
115
* Create a MockHttpServletRequestBuilder for an OPTIONS request.
116
* @param urlTemplate a URL template; the resulting URL will be encoded
117
* @param uriVariables zero or more URI variables
118
* @return the request builder
119
*/
120
public static MockHttpServletRequestBuilder options(String urlTemplate, Object... uriVariables);
121
122
/**
123
* Create a MockMultipartHttpServletRequestBuilder for a multipart request.
124
* @param urlTemplate a URL template; the resulting URL will be encoded
125
* @param uriVariables zero or more URI variables
126
* @return the request builder
127
*/
128
public static MockMultipartHttpServletRequestBuilder multipart(String urlTemplate, Object... uriVariables);
129
130
/**
131
* Create a RequestBuilder for an async dispatch from the MvcResult of the request.
132
* @param mvcResult the result from the request that initiated async processing
133
* @return the request builder for the async dispatch
134
*/
135
public static RequestBuilder asyncDispatch(MvcResult mvcResult);
136
}
137
138
/**
139
* Default builder for MockHttpServletRequest instances.
140
*/
141
public class MockHttpServletRequestBuilder implements ConfigurableSmartRequestBuilder<MockHttpServletRequestBuilder> {
142
143
/**
144
* Add a request parameter to the MockHttpServletRequest.
145
* @param name the parameter name
146
* @param values one or more values
147
* @return this request builder
148
*/
149
public MockHttpServletRequestBuilder param(String name, String... values);
150
151
/**
152
* Add multiple request parameters and values.
153
* @param params the parameters to add
154
* @return this request builder
155
*/
156
public MockHttpServletRequestBuilder params(MultiValueMap<String, String> params);
157
158
/**
159
* Add a header to the request.
160
* @param name the header name
161
* @param values one or more header values
162
* @return this request builder
163
*/
164
public MockHttpServletRequestBuilder header(String name, Object... values);
165
166
/**
167
* Add all headers from the given HttpHeaders object.
168
* @param httpHeaders the HttpHeaders object
169
* @return this request builder
170
*/
171
public MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders);
172
173
/**
174
* Set the content type of the request.
175
* @param contentType the content type
176
* @return this request builder
177
*/
178
public MockHttpServletRequestBuilder contentType(MediaType contentType);
179
180
/**
181
* Set the Accept header of the request.
182
* @param mediaTypes one or more media types
183
* @return this request builder
184
*/
185
public MockHttpServletRequestBuilder accept(MediaType... mediaTypes);
186
187
/**
188
* Set the content of the request body.
189
* @param content the body content
190
* @return this request builder
191
*/
192
public MockHttpServletRequestBuilder content(String content);
193
194
/**
195
* Set the content of the request body as a byte array.
196
* @param content the body content
197
* @return this request builder
198
*/
199
public MockHttpServletRequestBuilder content(byte[] content);
200
201
/**
202
* Add a cookie to the request.
203
* @param cookies one or more cookies
204
* @return this request builder
205
*/
206
public MockHttpServletRequestBuilder cookie(Cookie... cookies);
207
208
/**
209
* Set the locale of the request.
210
* @param locale the locale
211
* @return this request builder
212
*/
213
public MockHttpServletRequestBuilder locale(Locale locale);
214
215
/**
216
* Set the character encoding of the request.
217
* @param encoding the character encoding
218
* @return this request builder
219
*/
220
public MockHttpServletRequestBuilder characterEncoding(String encoding);
221
222
/**
223
* Apply the given RequestPostProcessor.
224
* @param postProcessor the post processor to apply
225
* @return this request builder
226
*/
227
public MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor);
228
}
229
```
230
231
### Result Actions and Matchers
232
233
Interfaces and factory classes for asserting the results of MockMvc requests.
234
235
```java { .api }
236
/**
237
* Allows applying actions, such as expectations, on the result of an executed request.
238
*/
239
public interface ResultActions {
240
241
/**
242
* Perform an expectation.
243
* @param matcher the expectation
244
* @return this ResultActions instance for method chaining
245
* @throws Exception if the expectation fails
246
*/
247
ResultActions andExpect(ResultMatcher matcher) throws Exception;
248
249
/**
250
* Perform multiple expectations.
251
* @param matchers the expectations
252
* @return this ResultActions instance for method chaining
253
* @throws Exception if any expectation fails
254
*/
255
ResultActions andExpectAll(ResultMatcher... matchers) throws Exception;
256
257
/**
258
* Perform a general action.
259
* @param handler the handler to execute
260
* @return this ResultActions instance for method chaining
261
* @throws Exception if the action fails
262
*/
263
ResultActions andDo(ResultHandler handler) throws Exception;
264
265
/**
266
* Return the result of the executed request for direct access to the results.
267
* @return the MvcResult
268
*/
269
MvcResult andReturn();
270
}
271
272
/**
273
* Factory for assertions on the result of a request executed through MockMvc.
274
*/
275
public abstract class MockMvcResultMatchers {
276
277
/**
278
* Access to request-related assertions.
279
* @return the RequestResultMatchers instance
280
*/
281
public static RequestResultMatchers request();
282
283
/**
284
* Access to response status assertions.
285
* @return the StatusResultMatchers instance
286
*/
287
public static StatusResultMatchers status();
288
289
/**
290
* Access to response header assertions.
291
* @return the HeaderResultMatchers instance
292
*/
293
public static HeaderResultMatchers header();
294
295
/**
296
* Access to response content assertions.
297
* @return the ContentResultMatchers instance
298
*/
299
public static ContentResultMatchers content();
300
301
/**
302
* Access to response body JSON path assertions.
303
* @param expression the JSON path expression
304
* @param args arguments to parameterize the JSON path expression with
305
* @return the JsonPathResultMatchers instance
306
*/
307
public static JsonPathResultMatchers jsonPath(String expression, Object... args);
308
309
/**
310
* Access to response body XPath assertions.
311
* @param expression the XPath expression
312
* @param args arguments to parameterize the XPath expression with
313
* @return the XpathResultMatchers instance
314
*/
315
public static XpathResultMatchers xpath(String expression, Object... args);
316
317
/**
318
* Access to model-related assertions.
319
* @return the ModelResultMatchers instance
320
*/
321
public static ModelResultMatchers model();
322
323
/**
324
* Access to view-related assertions.
325
* @return the ViewResultMatchers instance
326
*/
327
public static ViewResultMatchers view();
328
329
/**
330
* Access to flash attribute assertions.
331
* @return the FlashAttributeResultMatchers instance
332
*/
333
public static FlashAttributeResultMatchers flash();
334
335
/**
336
* Access to redirect URL assertions.
337
* @param expectedUrl the expected redirect URL
338
* @return the ResultMatcher instance
339
*/
340
public static ResultMatcher redirectedUrl(String expectedUrl);
341
342
/**
343
* Access to forwarded URL assertions.
344
* @param expectedUrl the expected forward URL
345
* @return the ResultMatcher instance
346
*/
347
public static ResultMatcher forwardedUrl(String expectedUrl);
348
349
/**
350
* Access to cookie-related assertions.
351
* @return the CookieResultMatchers instance
352
*/
353
public static CookieResultMatchers cookie();
354
}
355
356
/**
357
* Factory for response status assertions.
358
*/
359
public class StatusResultMatchers {
360
361
/**
362
* Assert the response status code is equal to the given status.
363
* @param status the expected status
364
* @return the ResultMatcher
365
*/
366
public ResultMatcher is(HttpStatus status);
367
368
/**
369
* Assert the response status code is equal to the given integer value.
370
* @param status the expected status code
371
* @return the ResultMatcher
372
*/
373
public ResultMatcher is(int status);
374
375
/**
376
* Assert the response status code is 200 (OK).
377
* @return the ResultMatcher
378
*/
379
public ResultMatcher isOk();
380
381
/**
382
* Assert the response status code is 201 (Created).
383
* @return the ResultMatcher
384
*/
385
public ResultMatcher isCreated();
386
387
/**
388
* Assert the response status code is 202 (Accepted).
389
* @return the ResultMatcher
390
*/
391
public ResultMatcher isAccepted();
392
393
/**
394
* Assert the response status code is 204 (No Content).
395
* @return the ResultMatcher
396
*/
397
public ResultMatcher isNoContent();
398
399
/**
400
* Assert the response status code is 400 (Bad Request).
401
* @return the ResultMatcher
402
*/
403
public ResultMatcher isBadRequest();
404
405
/**
406
* Assert the response status code is 401 (Unauthorized).
407
* @return the ResultMatcher
408
*/
409
public ResultMatcher isUnauthorized();
410
411
/**
412
* Assert the response status code is 403 (Forbidden).
413
* @return the ResultMatcher
414
*/
415
public ResultMatcher isForbidden();
416
417
/**
418
* Assert the response status code is 404 (Not Found).
419
* @return the ResultMatcher
420
*/
421
public ResultMatcher isNotFound();
422
423
/**
424
* Assert the response status code is 500 (Internal Server Error).
425
* @return the ResultMatcher
426
*/
427
public ResultMatcher isInternalServerError();
428
}
429
430
/**
431
* Factory for response content assertions.
432
*/
433
public class ContentResultMatchers {
434
435
/**
436
* Assert the response content type using a MediaType.
437
* @param contentType the expected content type
438
* @return the ResultMatcher
439
*/
440
public ResultMatcher contentType(MediaType contentType);
441
442
/**
443
* Assert the response content type as a String.
444
* @param contentType the expected content type
445
* @return the ResultMatcher
446
*/
447
public ResultMatcher contentType(String contentType);
448
449
/**
450
* Assert the response content encoding.
451
* @param characterEncoding the expected character encoding
452
* @return the ResultMatcher
453
*/
454
public ResultMatcher encoding(String characterEncoding);
455
456
/**
457
* Assert the response content as a String.
458
* @param expectedContent the expected content
459
* @return the ResultMatcher
460
*/
461
public ResultMatcher string(String expectedContent);
462
463
/**
464
* Assert the response content matches the given Hamcrest matcher.
465
* @param matcher the Hamcrest matcher
466
* @return the ResultMatcher
467
*/
468
public ResultMatcher string(Matcher<? super String> matcher);
469
470
/**
471
* Assert the response content as a byte array.
472
* @param expectedContent the expected content
473
* @return the ResultMatcher
474
*/
475
public ResultMatcher bytes(byte[] expectedContent);
476
477
/**
478
* Assert the response content as JSON.
479
* @param jsonContent the expected JSON content
480
* @return the ResultMatcher
481
*/
482
public ResultMatcher json(String jsonContent);
483
484
/**
485
* Assert the response content as JSON with strict comparison.
486
* @param jsonContent the expected JSON content
487
* @param strict whether to use strict comparison
488
* @return the ResultMatcher
489
*/
490
public ResultMatcher json(String jsonContent, boolean strict);
491
492
/**
493
* Assert the response content as XML.
494
* @param xmlContent the expected XML content
495
* @return the ResultMatcher
496
*/
497
public ResultMatcher xml(String xmlContent);
498
}
499
```
500
501
### Result Handlers
502
503
Factory for actions to perform on MockMvc results.
504
505
```java { .api }
506
/**
507
* Static factory methods for ResultHandler instances.
508
*/
509
public abstract class MockMvcResultHandlers {
510
511
/**
512
* Print the request and response details to System.out.
513
* @return the ResultHandler instance
514
*/
515
public static ResultHandler print();
516
517
/**
518
* Print the request and response details to the given OutputStream.
519
* @param stream the target stream
520
* @return the ResultHandler instance
521
*/
522
public static ResultHandler print(OutputStream stream);
523
524
/**
525
* Print the request and response details to the given Writer.
526
* @param writer the target writer
527
* @return the ResultHandler instance
528
*/
529
public static ResultHandler print(Writer writer);
530
531
/**
532
* Log the request and response details at DEBUG level using the given logger.
533
* @return the ResultHandler instance
534
*/
535
public static ResultHandler log();
536
}
537
```
538
539
### AssertJ Integration
540
541
Modern AssertJ-style fluent assertions for MockMvc testing.
542
543
```java { .api }
544
/**
545
* AssertJ-style assertions for MockMvc.
546
* Provides fluent API for testing Spring MVC applications.
547
*/
548
public class MockMvcTester {
549
550
/**
551
* Create a MockMvcTester instance from the given MockMvc.
552
* @param mockMvc the MockMvc instance
553
* @return the MockMvcTester instance
554
*/
555
public static MockMvcTester create(MockMvc mockMvc);
556
557
/**
558
* Perform a GET request.
559
* @param uriTemplate the URI template
560
* @param uriVariables URI variables
561
* @return the MockMvcRequestSpec for further configuration
562
*/
563
public MockMvcRequestSpec get(String uriTemplate, Object... uriVariables);
564
565
/**
566
* Perform a POST request.
567
* @param uriTemplate the URI template
568
* @param uriVariables URI variables
569
* @return the MockMvcRequestSpec for further configuration
570
*/
571
public MockMvcRequestSpec post(String uriTemplate, Object... uriVariables);
572
573
/**
574
* Perform a PUT request.
575
* @param uriTemplate the URI template
576
* @param uriVariables URI variables
577
* @return the MockMvcRequestSpec for further configuration
578
*/
579
public MockMvcRequestSpec put(String uriTemplate, Object... uriVariables);
580
581
/**
582
* Perform a PATCH request.
583
* @param uriTemplate the URI template
584
* @param uriVariables URI variables
585
* @return the MockMvcRequestSpec for further configuration
586
*/
587
public MockMvcRequestSpec patch(String uriTemplate, Object... uriVariables);
588
589
/**
590
* Perform a DELETE request.
591
* @param uriTemplate the URI template
592
* @param uriVariables URI variables
593
* @return the MockMvcRequestSpec for further configuration
594
*/
595
public MockMvcRequestSpec delete(String uriTemplate, Object... uriVariables);
596
}
597
598
/**
599
* AssertJ-style request specification for MockMvc testing.
600
*/
601
public class MockMvcRequestSpec {
602
603
/**
604
* Add a request parameter.
605
* @param name the parameter name
606
* @param values one or more parameter values
607
* @return this request spec
608
*/
609
public MockMvcRequestSpec param(String name, String... values);
610
611
/**
612
* Add a request header.
613
* @param name the header name
614
* @param values one or more header values
615
* @return this request spec
616
*/
617
public MockMvcRequestSpec header(String name, Object... values);
618
619
/**
620
* Set the content type.
621
* @param contentType the content type
622
* @return this request spec
623
*/
624
public MockMvcRequestSpec contentType(MediaType contentType);
625
626
/**
627
* Set the request content.
628
* @param content the content
629
* @return this request spec
630
*/
631
public MockMvcRequestSpec content(String content);
632
633
/**
634
* Execute the request and return assertions.
635
* @return the AbstractMockMvcResultAssert for assertions
636
*/
637
public AbstractMockMvcResultAssert<?> exchange();
638
}
639
```
640
641
**Usage Examples:**
642
643
```java
644
import org.springframework.test.web.servlet.MockMvc;
645
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
646
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
647
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
648
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
649
650
@SpringJUnitWebConfig(WebConfig.class)
651
class UserControllerTest {
652
653
@Autowired
654
private MockMvc mockMvc;
655
656
@Test
657
void shouldReturnUserList() throws Exception {
658
mockMvc.perform(get("/users")
659
.accept(MediaType.APPLICATION_JSON))
660
.andExpect(status().isOk())
661
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
662
.andExpect(jsonPath("$").isArray())
663
.andExpect(jsonPath("$[0].name").value("John"))
664
.andDo(print());
665
}
666
667
@Test
668
void shouldCreateUser() throws Exception {
669
String userJson = """
670
{
671
"name": "Jane Doe",
672
"email": "jane@example.com"
673
}
674
""";
675
676
mockMvc.perform(post("/users")
677
.contentType(MediaType.APPLICATION_JSON)
678
.content(userJson))
679
.andExpect(status().isCreated())
680
.andExpect(header().exists("Location"))
681
.andExpect(jsonPath("$.id").exists())
682
.andExpect(jsonPath("$.name").value("Jane Doe"));
683
}
684
685
@Test
686
void shouldHandleValidationErrors() throws Exception {
687
String invalidUserJson = """
688
{
689
"name": "",
690
"email": "invalid-email"
691
}
692
""";
693
694
mockMvc.perform(post("/users")
695
.contentType(MediaType.APPLICATION_JSON)
696
.content(invalidUserJson))
697
.andExpect(status().isBadRequest())
698
.andExpect(jsonPath("$.errors").isArray())
699
.andExpect(jsonPath("$.errors[?(@.field == 'name')]").exists())
700
.andExpect(jsonPath("$.errors[?(@.field == 'email')]").exists());
701
}
702
}
703
704
// Standalone setup example
705
@Test
706
void standaloneControllerTest() throws Exception {
707
UserController controller = new UserController(mockUserService);
708
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller)
709
.setControllerAdvice(new GlobalExceptionHandler())
710
.addFilter(new CorsFilter())
711
.build();
712
713
mockMvc.perform(get("/users/1"))
714
.andExpect(status().isOk());
715
}
716
717
// AssertJ style testing
718
@Test
719
void assertJStyleTest() {
720
MockMvcTester tester = MockMvcTester.create(mockMvc);
721
722
tester.get("/users/{id}", 1)
723
.exchange()
724
.andExpect(status().isOk())
725
.andExpect(jsonPath("$.name").value("John"));
726
}
727
```
728
729
## Types
730
731
```java { .api }
732
/**
733
* Contract for building a MockHttpServletRequest.
734
*/
735
public interface RequestBuilder {
736
737
/**
738
* Build the request.
739
* @param servletContext the ServletContext to use
740
* @return the built MockHttpServletRequest
741
*/
742
MockHttpServletRequest buildRequest(ServletContext servletContext);
743
}
744
745
/**
746
* A contract for matching the result of an executed request.
747
*/
748
public interface ResultMatcher {
749
750
/**
751
* Assert the result of an executed request.
752
* @param result the result of the executed request
753
* @throws Exception if the assertion fails
754
*/
755
void match(MvcResult result) throws Exception;
756
}
757
758
/**
759
* A contract that can be used to apply actions to the result of an executed request.
760
*/
761
public interface ResultHandler {
762
763
/**
764
* Apply the action to the given result.
765
* @param result the result of the executed request
766
* @throws Exception if applying the action fails
767
*/
768
void handle(MvcResult result) throws Exception;
769
}
770
771
/**
772
* Provides access to the result of an executed request.
773
*/
774
public interface MvcResult {
775
776
/**
777
* Return the performed request.
778
* @return the request (never null)
779
*/
780
MockHttpServletRequest getRequest();
781
782
/**
783
* Return the resulting response.
784
* @return the response (never null)
785
*/
786
MockHttpServletResponse getResponse();
787
788
/**
789
* Return the executed handler.
790
* @return the handler (may be null)
791
*/
792
@Nullable
793
Object getHandler();
794
795
/**
796
* Return the HandlerInterceptor instances applied during request processing.
797
* @return the interceptor chain (may be null)
798
*/
799
@Nullable
800
HandlerInterceptor[] getInterceptors();
801
802
/**
803
* Return the ModelAndView prepared by the handler.
804
* @return the ModelAndView (may be null)
805
*/
806
@Nullable
807
ModelAndView getModelAndView();
808
809
/**
810
* Return any exception raised by a handler and successfully resolved through a HandlerExceptionResolver.
811
* @return the resolved exception (may be null)
812
*/
813
@Nullable
814
Exception getResolvedException();
815
816
/**
817
* Return the "output" flash attributes saved during request processing.
818
* @return the flash attributes (never null)
819
*/
820
FlashMap getFlashMap();
821
}
822
823
/**
824
* Contract for post-processing a MockHttpServletRequest.
825
*/
826
public interface RequestPostProcessor {
827
828
/**
829
* Post-process the given MockHttpServletRequest.
830
* @param request the request to post-process
831
* @return the processed request (may be the same instance or a new one)
832
*/
833
MockHttpServletRequest postProcessRequest(MockHttpServletRequest request);
834
}
835
```
836
837
### WebTestClient
838
839
Client for testing web servers using a fluent API, supporting both mock and live server testing for reactive and traditional Spring MVC applications.
840
841
```java { .api }
842
/**
843
* Client for testing web servers that uses WebClient internally to perform requests
844
* while also providing a fluent API to verify responses. Can connect to any server
845
* over HTTP, or to a WebFlux application via mock request and response objects.
846
*/
847
public interface WebTestClient {
848
849
/**
850
* Prepare an HTTP GET request.
851
* @return a spec for specifying the target URL
852
*/
853
RequestHeadersUriSpec<?> get();
854
855
/**
856
* Prepare an HTTP HEAD request.
857
* @return a spec for specifying the target URL
858
*/
859
RequestHeadersUriSpec<?> head();
860
861
/**
862
* Prepare an HTTP POST request.
863
* @return a spec for specifying the target URL
864
*/
865
RequestBodyUriSpec post();
866
867
/**
868
* Prepare an HTTP PUT request.
869
* @return a spec for specifying the target URL
870
*/
871
RequestBodyUriSpec put();
872
873
/**
874
* Prepare an HTTP PATCH request.
875
* @return a spec for specifying the target URL
876
*/
877
RequestBodyUriSpec patch();
878
879
/**
880
* Prepare an HTTP DELETE request.
881
* @return a spec for specifying the target URL
882
*/
883
RequestHeadersUriSpec<?> delete();
884
885
/**
886
* Prepare an HTTP OPTIONS request.
887
* @return a spec for specifying the target URL
888
*/
889
RequestHeadersUriSpec<?> options();
890
891
/**
892
* Prepare a request for the specified HttpMethod.
893
* @param method the HTTP method
894
* @return a spec for specifying the target URL
895
*/
896
RequestBodyUriSpec method(HttpMethod method);
897
898
/**
899
* Return a builder to mutate properties of this web test client.
900
* @return a builder for further configuration
901
*/
902
Builder mutate();
903
904
/**
905
* Mutate this WebTestClient, apply the given configurer, and build a new instance.
906
* @param configurer the configurer to apply
907
* @return a new WebTestClient instance
908
*/
909
WebTestClient mutateWith(WebTestClientConfigurer configurer);
910
911
/**
912
* Create a WebTestClient bound to the given controller.
913
* @param controllers one or more controllers to test
914
* @return a ControllerSpec for further configuration
915
*/
916
static ControllerSpec bindToController(Object... controllers);
917
918
/**
919
* Create a WebTestClient bound to the given RouterFunction.
920
* @param routerFunction the RouterFunction to test
921
* @return a RouterFunctionSpec for further configuration
922
*/
923
static RouterFunctionSpec bindToRouterFunction(RouterFunction<?> routerFunction);
924
925
/**
926
* Create a WebTestClient bound to the given ApplicationContext.
927
* @param applicationContext the context to load configuration from
928
* @return a MockServerSpec for further configuration
929
*/
930
static MockServerSpec<?> bindToApplicationContext(ApplicationContext applicationContext);
931
932
/**
933
* Create a WebTestClient bound to the given WebHandler.
934
* @param webHandler the WebHandler to test
935
* @return a MockServerSpec for further configuration
936
*/
937
static MockServerSpec<?> bindToWebHandler(WebHandler webHandler);
938
939
/**
940
* Create a WebTestClient for integration testing against a live server.
941
* @return a Builder for further configuration
942
*/
943
static Builder bindToServer();
944
945
/**
946
* Create a WebTestClient for integration testing with a specific connector.
947
* @param connector the ClientHttpConnector to use
948
* @return a Builder for further configuration
949
*/
950
static Builder bindToServer(ClientHttpConnector connector);
951
}
952
953
/**
954
* Contract for encapsulating customizations to WebTestClient.Builder.
955
*/
956
public interface WebTestClientConfigurer {
957
958
/**
959
* Invoked once only, immediately (i.e. before this method returns).
960
* @param builder the WebTestClient builder to customize
961
* @param httpHandlerBuilder the builder for the "mock server" HttpHandler
962
* @param connector the connector for "live" integration tests
963
*/
964
void afterConfigurerAdded(WebTestClient.Builder builder,
965
@Nullable WebHttpHandlerBuilder httpHandlerBuilder,
966
@Nullable ClientHttpConnector connector);
967
}
968
969
/**
970
* Contract that frameworks or applications can use to pre-package a set of
971
* customizations to WebTestClient.MockServerSpec and expose that as a shortcut.
972
*/
973
public interface MockServerConfigurer extends WebTestClientConfigurer {
974
975
/**
976
* Invoked immediately, i.e. before this method returns.
977
* @param serverSpec the MockServerSpec to customize
978
*/
979
default void afterConfigureAdded(WebTestClient.MockServerSpec<?> serverSpec) {
980
}
981
982
/**
983
* Invoked just before the mock server is created.
984
* @param builder the builder for the HttpHandler that will handle requests
985
*/
986
default void beforeServerCreated(WebHttpHandlerBuilder builder) {
987
}
988
}
989
990
/**
991
* Specification for creating a WebTestClient bound to MockMvc.
992
*/
993
public final class MockMvcWebTestClient {
994
995
/**
996
* Create a WebTestClient bound to the given controller.
997
* @param controllers one or more controllers to test
998
* @return a ControllerSpec for further configuration
999
*/
1000
public static WebTestClient.ControllerSpec bindToController(Object... controllers);
1001
1002
/**
1003
* Create a WebTestClient bound to the given RouterFunction.
1004
* @param routerFunctions one or more RouterFunction instances
1005
* @return a RouterFunctionSpec for further configuration
1006
*/
1007
public static WebTestClient.RouterFunctionSpec bindToRouterFunction(RouterFunction<?>... routerFunctions);
1008
1009
/**
1010
* Create a WebTestClient bound to the given WebApplicationContext.
1011
* @param context the WebApplicationContext to use
1012
* @return a MockMvcServerSpec for further configuration
1013
*/
1014
public static MockMvcServerSpec<?> bindToApplicationContext(WebApplicationContext context);
1015
1016
/**
1017
* Create a WebTestClient bound to the given MockMvc instance.
1018
* @param mockMvc the MockMvc instance to bind to
1019
* @return a Builder for further configuration
1020
*/
1021
public static WebTestClient.Builder bindTo(MockMvc mockMvc);
1022
1023
/**
1024
* Return ResultActions to further verify the response.
1025
* @param exchangeResult the result from WebTestClient
1026
* @return ResultActions for MockMvc-style verification
1027
*/
1028
public static ResultActions resultActionsFor(ExchangeResult exchangeResult);
1029
}
1030
```
1031
1032
**Usage Examples:**
1033
1034
```java
1035
// Controller testing
1036
WebTestClient client = WebTestClient
1037
.bindToController(new PersonController())
1038
.build();
1039
1040
client.get().uri("/persons/1")
1041
.accept(MediaType.APPLICATION_JSON)
1042
.exchange()
1043
.expectStatus().isOk()
1044
.expectBody(Person.class)
1045
.value(person -> {
1046
assertEquals("John", person.getName());
1047
assertEquals(30, person.getAge());
1048
});
1049
1050
// Application context testing
1051
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
1052
class IntegrationTest {
1053
1054
@Autowired
1055
private TestRestTemplate restTemplate;
1056
1057
private WebTestClient webTestClient;
1058
1059
@BeforeEach
1060
void setUp() {
1061
webTestClient = WebTestClient
1062
.bindToServer()
1063
.baseUrl("http://localhost:" + port)
1064
.build();
1065
}
1066
1067
@Test
1068
void testReactiveEndpoint() {
1069
webTestClient.get().uri("/api/persons")
1070
.exchange()
1071
.expectStatus().isOk()
1072
.expectBody()
1073
.jsonPath("$[0].name").isEqualTo("John")
1074
.jsonPath("$[0].age").isEqualTo(30);
1075
}
1076
}
1077
1078
// JSON content verification
1079
webTestClient.post().uri("/persons")
1080
.contentType(MediaType.APPLICATION_JSON)
1081
.bodyValue(new Person("Jane", 25))
1082
.exchange()
1083
.expectStatus().isCreated()
1084
.expectBody().json("""
1085
{
1086
"name": "Jane",
1087
"age": 25,
1088
"id": 2
1089
}
1090
""");
1091
1092
// Streaming response testing
1093
webTestClient.get().uri("/persons/stream")
1094
.accept(MediaType.APPLICATION_NDJSON)
1095
.exchange()
1096
.expectStatus().isOk()
1097
.expectHeader().contentType(MediaType.APPLICATION_NDJSON)
1098
.expectBodyList(Person.class)
1099
.hasSize(10);
1100
```