0
# MockMvc Integration
1
2
Comprehensive MockMvc integration providing request post-processors, configurers, and result matchers for testing web security in servlet-based Spring applications. This integration allows testing of HTTP security concerns including authentication, authorization, CSRF protection, and various authentication mechanisms.
3
4
## Setup
5
6
### MockMvc Configuration
7
8
Configure MockMvc with Spring Security support using the configurer.
9
10
```java { .api }
11
/**
12
* Spring Security MockMvc configurers
13
*/
14
public class SecurityMockMvcConfigurers {
15
/**
16
* Auto-configure Spring Security with MockMvc using default filter chain
17
* @return MockMvcConfigurer for Spring Security integration
18
*/
19
public static MockMvcConfigurer springSecurity();
20
21
/**
22
* Configure Spring Security with MockMvc using specific filter chain
23
* @param springSecurityFilterChain The security filter chain to use
24
* @return MockMvcConfigurer for Spring Security integration
25
*/
26
public static MockMvcConfigurer springSecurity(Filter springSecurityFilterChain);
27
}
28
```
29
30
**Usage Examples:**
31
32
```java
33
@SpringBootTest
34
@AutoConfigureTestDatabase
35
public class SecurityIntegrationTest {
36
37
@Autowired
38
private WebApplicationContext context;
39
40
private MockMvc mockMvc;
41
42
@BeforeEach
43
public void setup() {
44
mockMvc = MockMvcBuilders
45
.webAppContextSetup(context)
46
.apply(springSecurity()) // Essential for security testing
47
.build();
48
}
49
}
50
```
51
52
## Request Post-Processors
53
54
### Authentication Setup
55
56
Core authentication setup methods for establishing security contexts in requests.
57
58
```java { .api }
59
/**
60
* Security request post-processors for MockMvc
61
*/
62
public class SecurityMockMvcRequestPostProcessors {
63
64
/**
65
* Uses the SecurityContext from TestSecurityContextHolder
66
* @return RequestPostProcessor that applies test security context
67
*/
68
public static RequestPostProcessor testSecurityContext();
69
70
/**
71
* Sets a specific Authentication in the SecurityContext
72
* @param authentication The authentication to use
73
* @return RequestPostProcessor that applies the authentication
74
*/
75
public static RequestPostProcessor authentication(Authentication authentication);
76
77
/**
78
* Creates anonymous authentication
79
* @return RequestPostProcessor for anonymous authentication
80
*/
81
public static RequestPostProcessor anonymous();
82
83
/**
84
* Sets a specific SecurityContext
85
* @param securityContext The security context to use
86
* @return RequestPostProcessor that applies the security context
87
*/
88
public static RequestPostProcessor securityContext(SecurityContext securityContext);
89
}
90
```
91
92
**Usage Examples:**
93
94
```java
95
@Test
96
public void testWithAuthentication() throws Exception {
97
Authentication auth = new UsernamePasswordAuthenticationToken(
98
"user", "password",
99
Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))
100
);
101
102
mockMvc.perform(get("/secure")
103
.with(authentication(auth)))
104
.andExpect(status().isOk());
105
}
106
107
@Test
108
@WithMockUser(username = "testuser")
109
public void testWithSecurityContext() throws Exception {
110
mockMvc.perform(get("/user-info")
111
.with(testSecurityContext())) // Uses @WithMockUser context
112
.andExpected(status().isOk());
113
}
114
```
115
116
### User Authentication
117
118
Create user-based authentication with configurable roles and authorities.
119
120
```java { .api }
121
/**
122
* Creates basic user authentication with username
123
* @param username The username for authentication
124
* @return UserRequestPostProcessor for further configuration
125
*/
126
public static UserRequestPostProcessor user(String username);
127
128
/**
129
* Creates user authentication from UserDetails
130
* @param user The UserDetails instance
131
* @return RequestPostProcessor with user authentication
132
*/
133
public static RequestPostProcessor user(UserDetails user);
134
135
/**
136
* Fluent configuration for user authentication
137
*/
138
public interface UserRequestPostProcessor extends RequestPostProcessor {
139
/** Set user roles (automatically prefixed with "ROLE_") */
140
UserRequestPostProcessor roles(String... roles);
141
142
/** Set granted authorities */
143
UserRequestPostProcessor authorities(GrantedAuthority... authorities);
144
145
/** Set user password */
146
UserRequestPostProcessor password(String password);
147
}
148
```
149
150
**Usage Examples:**
151
152
```java
153
@Test
154
public void testWithBasicUser() throws Exception {
155
mockMvc.perform(get("/user-endpoint")
156
.with(user("john")))
157
.andExpect(status().isOk());
158
}
159
160
@Test
161
public void testWithUserRoles() throws Exception {
162
mockMvc.perform(get("/admin-endpoint")
163
.with(user("admin").roles("ADMIN", "USER")))
164
.andExpect(status().isOk());
165
}
166
167
@Test
168
public void testWithUserAuthorities() throws Exception {
169
mockMvc.perform(get("/privileged-endpoint")
170
.with(user("manager")
171
.authorities(
172
new SimpleGrantedAuthority("READ_PRIVILEGES"),
173
new SimpleGrantedAuthority("WRITE_PRIVILEGES")
174
)))
175
.andExpect(status().isOk());
176
}
177
178
@Test
179
public void testWithUserDetails() throws Exception {
180
UserDetails userDetails = User.builder()
181
.username("alice")
182
.password("secret")
183
.roles("USER", "MANAGER")
184
.build();
185
186
mockMvc.perform(get("/manager-endpoint")
187
.with(user(userDetails)))
188
.andExpect(status().isOk());
189
}
190
```
191
192
### HTTP Authentication
193
194
Support for HTTP Basic and Digest authentication mechanisms.
195
196
```java { .api }
197
/**
198
* HTTP Basic authentication
199
* @param username The username
200
* @param password The password
201
* @return RequestPostProcessor with HTTP Basic authentication
202
*/
203
public static RequestPostProcessor httpBasic(String username, String password);
204
205
/**
206
* HTTP Digest authentication with default username
207
* @return DigestRequestPostProcessor for configuration
208
*/
209
public static DigestRequestPostProcessor digest();
210
211
/**
212
* HTTP Digest authentication with specific username
213
* @param username The username for digest authentication
214
* @return DigestRequestPostProcessor for configuration
215
*/
216
public static DigestRequestPostProcessor digest(String username);
217
218
/**
219
* Fluent configuration for HTTP Digest authentication
220
*/
221
public interface DigestRequestPostProcessor extends RequestPostProcessor {
222
// Additional digest-specific configuration methods
223
}
224
```
225
226
**Usage Examples:**
227
228
```java
229
@Test
230
public void testHttpBasicAuth() throws Exception {
231
mockMvc.perform(get("/api/data")
232
.with(httpBasic("apiuser", "apipass")))
233
.andExpect(status().isOk());
234
}
235
236
@Test
237
public void testHttpDigestAuth() throws Exception {
238
mockMvc.perform(get("/api/secure")
239
.with(digest("digestuser")))
240
.andExpect(status().isOk());
241
}
242
```
243
244
### Certificate Authentication
245
246
X.509 certificate-based authentication support.
247
248
```java { .api }
249
/**
250
* X.509 certificate authentication
251
* @param certificates The X.509 certificates to use
252
* @return RequestPostProcessor with certificate authentication
253
*/
254
public static RequestPostProcessor x509(X509Certificate... certificates);
255
256
/**
257
* X.509 certificate authentication from resource
258
* @param resourceName The resource name containing the certificate
259
* @return RequestPostProcessor with certificate authentication
260
*/
261
public static RequestPostProcessor x509(String resourceName);
262
```
263
264
**Usage Examples:**
265
266
```java
267
@Test
268
public void testCertificateAuth() throws Exception {
269
mockMvc.perform(get("/cert-required")
270
.with(x509("classpath:test-cert.pem")))
271
.andExpect(status().isOk());
272
}
273
```
274
275
### OAuth2 and JWT Authentication
276
277
Comprehensive support for modern authentication mechanisms including JWT and OAuth2.
278
279
```java { .api }
280
/**
281
* JWT authentication with default configuration
282
* @return JwtRequestPostProcessor for configuration
283
*/
284
public static JwtRequestPostProcessor jwt();
285
286
/**
287
* OAuth2 opaque token authentication
288
* @return OpaqueTokenRequestPostProcessor for configuration
289
*/
290
public static OpaqueTokenRequestPostProcessor opaqueToken();
291
292
/**
293
* OAuth2 login authentication
294
* @return OAuth2LoginRequestPostProcessor for configuration
295
*/
296
public static OAuth2LoginRequestPostProcessor oauth2Login();
297
298
/**
299
* OIDC login authentication
300
* @return OidcLoginRequestPostProcessor for configuration
301
*/
302
public static OidcLoginRequestPostProcessor oidcLogin();
303
304
/**
305
* OAuth2 client configuration
306
* @return OAuth2ClientRequestPostProcessor for configuration
307
*/
308
public static OAuth2ClientRequestPostProcessor oauth2Client();
309
310
/**
311
* OAuth2 client with specific registration
312
* @param registrationId The client registration ID
313
* @return OAuth2ClientRequestPostProcessor for configuration
314
*/
315
public static OAuth2ClientRequestPostProcessor oauth2Client(String registrationId);
316
```
317
318
**JWT Configuration Interface:**
319
320
```java { .api }
321
/**
322
* Fluent configuration for JWT authentication
323
*/
324
public interface JwtRequestPostProcessor extends RequestPostProcessor {
325
/**
326
* Configure JWT using builder consumer
327
* @param jwtBuilderConsumer Consumer to configure JWT builder
328
* @return JwtRequestPostProcessor for chaining
329
*/
330
JwtRequestPostProcessor jwt(Consumer<Jwt.Builder> jwtBuilderConsumer);
331
332
/**
333
* Use specific JWT instance
334
* @param jwt The JWT to use
335
* @return JwtRequestPostProcessor for chaining
336
*/
337
JwtRequestPostProcessor jwt(Jwt jwt);
338
339
/**
340
* Set authorities for JWT authentication
341
* @param authorities The granted authorities
342
* @return JwtRequestPostProcessor for chaining
343
*/
344
JwtRequestPostProcessor authorities(Collection<GrantedAuthority> authorities);
345
}
346
```
347
348
**Usage Examples:**
349
350
```java
351
@Test
352
public void testWithJwt() throws Exception {
353
mockMvc.perform(get("/api/jwt-secured")
354
.with(jwt()
355
.jwt(jwt -> jwt
356
.claim("sub", "user123")
357
.claim("scope", "read write"))
358
.authorities(
359
new SimpleGrantedAuthority("SCOPE_read"),
360
new SimpleGrantedAuthority("SCOPE_write")
361
)))
362
.andExpect(status().isOk());
363
}
364
365
@Test
366
public void testWithOAuth2Login() throws Exception {
367
mockMvc.perform(get("/oauth2/user")
368
.with(oauth2Login()
369
.attributes(attrs -> {
370
attrs.put("sub", "12345");
371
attrs.put("name", "John Doe");
372
})
373
.authorities(new SimpleGrantedAuthority("ROLE_USER"))))
374
.andExpected(status().isOk());
375
}
376
377
@Test
378
public void testWithOidcLogin() throws Exception {
379
mockMvc.perform(get("/oidc/userinfo")
380
.with(oidcLogin()
381
.idToken(token -> token
382
.claim("sub", "user123")
383
.claim("email", "user@example.com"))
384
.userInfo(userInfo -> userInfo
385
.claim("given_name", "John")
386
.claim("family_name", "Doe"))))
387
.andExpect(status().isOk());
388
}
389
```
390
391
### CSRF Protection
392
393
CSRF token support for testing CSRF-protected endpoints.
394
395
```java { .api }
396
/**
397
* Valid CSRF token for testing
398
* @return CsrfRequestPostProcessor for configuration
399
*/
400
public static CsrfRequestPostProcessor csrf();
401
402
/**
403
* Fluent configuration for CSRF tokens
404
*/
405
public interface CsrfRequestPostProcessor extends RequestPostProcessor {
406
/**
407
* Send CSRF token as HTTP header instead of parameter
408
* @return CsrfRequestPostProcessor for chaining
409
*/
410
CsrfRequestPostProcessor asHeader();
411
412
/**
413
* Use an invalid CSRF token for testing failure scenarios
414
* @return CsrfRequestPostProcessor for chaining
415
*/
416
CsrfRequestPostProcessor useInvalidToken();
417
}
418
```
419
420
**Usage Examples:**
421
422
```java
423
@Test
424
public void testCsrfProtectedEndpoint() throws Exception {
425
mockMvc.perform(post("/form-submit")
426
.param("data", "test")
427
.with(csrf()) // Valid CSRF token
428
.with(user("user")))
429
.andExpect(status().is3xxRedirection());
430
}
431
432
@Test
433
public void testCsrfTokenAsHeader() throws Exception {
434
mockMvc.perform(post("/api/update")
435
.content("{\"data\":\"test\"}")
436
.contentType(MediaType.APPLICATION_JSON)
437
.with(csrf().asHeader()) // CSRF token in header
438
.with(user("user")))
439
.andExpect(status().isOk());
440
}
441
442
@Test
443
public void testInvalidCsrfToken() throws Exception {
444
mockMvc.perform(post("/protected")
445
.with(csrf().useInvalidToken())
446
.with(user("user")))
447
.andExpect(status().isForbidden());
448
}
449
```
450
451
## Result Matchers
452
453
Test authentication state and user details in responses.
454
455
```java { .api }
456
/**
457
* Security result matchers for MockMvc
458
*/
459
public class SecurityMockMvcResultMatchers {
460
461
/**
462
* Verify that user is authenticated
463
* @return AuthenticatedMatcher for further verification
464
*/
465
public static AuthenticatedMatcher authenticated();
466
467
/**
468
* Verify that user is not authenticated
469
* @return ResultMatcher for unauthenticated verification
470
*/
471
public static ResultMatcher unauthenticated();
472
}
473
474
/**
475
* Fluent matcher for authenticated user details
476
*/
477
public interface AuthenticatedMatcher extends ResultMatcher {
478
/** Verify the username */
479
AuthenticatedMatcher withUsername(String expected);
480
481
/** Verify user roles */
482
AuthenticatedMatcher withRoles(String... roles);
483
484
/** Verify user authorities */
485
AuthenticatedMatcher withAuthorities(Collection<? extends GrantedAuthority> expected);
486
487
/** Verify specific Authentication object */
488
AuthenticatedMatcher withAuthentication(Authentication expected);
489
490
/** Verify SecurityContext */
491
AuthenticatedMatcher withSecurityContext(SecurityContext expected);
492
}
493
```
494
495
**Usage Examples:**
496
497
```java
498
@Test
499
public void testAuthenticationState() throws Exception {
500
mockMvc.perform(get("/user-info")
501
.with(user("john").roles("USER", "ADMIN")))
502
.andExpect(status().isOk())
503
.andExpect(authenticated()
504
.withUsername("john")
505
.withRoles("USER", "ADMIN"));
506
}
507
508
@Test
509
public void testUnauthenticatedAccess() throws Exception {
510
mockMvc.perform(get("/public"))
511
.andExpect(status().isOk())
512
.andExpect(unauthenticated());
513
}
514
515
@Test
516
public void testSpecificAuthorities() throws Exception {
517
mockMvc.perform(get("/privileged")
518
.with(user("manager")
519
.authorities(
520
new SimpleGrantedAuthority("READ_PRIVILEGES"),
521
new SimpleGrantedAuthority("WRITE_PRIVILEGES")
522
)))
523
.andExpect(authenticated()
524
.withAuthorities(Arrays.asList(
525
new SimpleGrantedAuthority("READ_PRIVILEGES"),
526
new SimpleGrantedAuthority("WRITE_PRIVILEGES")
527
)));
528
}
529
```
530
531
## Request Builders
532
533
### SecurityMockMvcRequestBuilders
534
535
Enhanced request builders with security-specific functionality for form login and logout scenarios.
536
537
```java { .api }
538
/**
539
* Security-enhanced request builders for form authentication flows
540
*/
541
public class SecurityMockMvcRequestBuilders {
542
543
/**
544
* Creates a form login request to default "/login" endpoint
545
* @return FormLoginRequestBuilder for configuration
546
*/
547
public static FormLoginRequestBuilder formLogin();
548
549
/**
550
* Creates a form login request to specified endpoint
551
* @param loginProcessingUrl The URL to POST the login form to
552
* @return FormLoginRequestBuilder for configuration
553
*/
554
public static FormLoginRequestBuilder formLogin(String loginProcessingUrl);
555
556
/**
557
* Creates a logout request to default "/logout" endpoint
558
* @return LogoutRequestBuilder for configuration
559
*/
560
public static LogoutRequestBuilder logout();
561
562
/**
563
* Creates a logout request to specified endpoint
564
* @param logoutUrl The logout URL to POST to
565
* @return LogoutRequestBuilder for configuration
566
*/
567
public static LogoutRequestBuilder logout(String logoutUrl);
568
}
569
```
570
571
### FormLoginRequestBuilder
572
573
Fluent builder for form-based login requests with CSRF protection.
574
575
```java { .api }
576
/**
577
* Builder for form login requests with automatic CSRF token inclusion
578
*/
579
public interface FormLoginRequestBuilder extends RequestBuilder {
580
/** Set the login processing URL */
581
FormLoginRequestBuilder loginProcessingUrl(String loginProcessingUrl);
582
583
/** Set the login processing URL with URI variables */
584
FormLoginRequestBuilder loginProcessingUrl(String loginProcessingUrl, Object... uriVars);
585
586
/** Set the username parameter name (default: "username") */
587
FormLoginRequestBuilder userParameter(String usernameParameter);
588
589
/** Set the password parameter name (default: "password") */
590
FormLoginRequestBuilder passwordParam(String passwordParameter);
591
592
/** Set the username value (default: "user") */
593
FormLoginRequestBuilder user(String username);
594
595
/** Set the password value (default: "password") */
596
FormLoginRequestBuilder password(String password);
597
598
/** Set both username parameter name and value */
599
FormLoginRequestBuilder user(String usernameParameter, String username);
600
601
/** Set both password parameter name and value */
602
FormLoginRequestBuilder password(String passwordParameter, String password);
603
604
/** Set the Accept header media type */
605
FormLoginRequestBuilder acceptMediaType(MediaType acceptMediaType);
606
}
607
```
608
609
### LogoutRequestBuilder
610
611
Fluent builder for logout requests with CSRF protection.
612
613
```java { .api }
614
/**
615
* Builder for logout requests with automatic CSRF token inclusion
616
*/
617
public interface LogoutRequestBuilder extends RequestBuilder {
618
/** Set the logout URL (default: "/logout") */
619
LogoutRequestBuilder logoutUrl(String logoutUrl);
620
621
/** Set the logout URL with URI variables */
622
LogoutRequestBuilder logoutUrl(String logoutUrl, Object... uriVars);
623
}
624
```
625
626
**Usage Examples:**
627
628
```java
629
@Test
630
public void testFormLogin() throws Exception {
631
mockMvc.perform(formLogin()
632
.user("john")
633
.password("secret"))
634
.andExpect(status().is3xxRedirection())
635
.andExpect(authenticated().withUsername("john"));
636
}
637
638
@Test
639
public void testCustomFormLogin() throws Exception {
640
mockMvc.perform(formLogin("/custom-login")
641
.userParameter("email")
642
.passwordParam("pass")
643
.user("john@example.com")
644
.password("secret"))
645
.andExpect(status().is3xxRedirection());
646
}
647
648
@Test
649
public void testLogout() throws Exception {
650
mockMvc.perform(logout()
651
.with(user("testuser")))
652
.andExpect(status().is3xxRedirection())
653
.andExpect(unauthenticated());
654
}
655
656
@Test
657
public void testCustomLogout() throws Exception {
658
mockMvc.perform(logout("/custom-logout")
659
.with(user("testuser")))
660
.andExpect(status().is3xxRedirection());
661
}
662
```
663
664
## Common Testing Patterns
665
666
### Comprehensive Security Test
667
668
```java
669
@SpringBootTest
670
@AutoConfigureTestDatabase
671
public class ComprehensiveSecurityTest {
672
673
@Autowired
674
private WebApplicationContext context;
675
676
private MockMvc mockMvc;
677
678
@BeforeEach
679
public void setup() {
680
mockMvc = MockMvcBuilders
681
.webAppContextSetup(context)
682
.apply(springSecurity())
683
.build();
684
}
685
686
@Test
687
public void testCompleteUserFlow() throws Exception {
688
// Test unauthenticated access
689
mockMvc.perform(get("/secure"))
690
.andExpect(status().isUnauthorized())
691
.andExpect(unauthenticated());
692
693
// Test authenticated access
694
mockMvc.perform(get("/secure")
695
.with(user("john").roles("USER")))
696
.andExpect(status().isOk())
697
.andExpect(authenticated().withUsername("john"));
698
699
// Test admin-only endpoint
700
mockMvc.perform(get("/admin")
701
.with(user("john").roles("USER")))
702
.andExpect(status().isForbidden());
703
704
mockMvc.perform(get("/admin")
705
.with(user("admin").roles("ADMIN")))
706
.andExpect(status().isOk());
707
}
708
709
@Test
710
public void testFormSubmissionWithCsrf() throws Exception {
711
mockMvc.perform(post("/form")
712
.param("data", "test")
713
.with(csrf())
714
.with(user("user")))
715
.andExpect(status().is3xxRedirection());
716
}
717
}
718
```