Selaa lähdekoodia

Extract test subsections

Issue: gh-2567
Rob Winch 7 vuotta sitten
vanhempi
commit
ae9075c023

+ 0 - 898
docs/manual/src/docs/asciidoc/_includes/test.adoc

@@ -1,898 +0,0 @@
-[[test]]
-= Testing
-
-This section describes the testing support provided by Spring Security.
-
-[TIP]
-====
-To use the Spring Security test support, you must include `spring-security-test-{spring-security-version}.jar` as a dependency of your project.
-====
-
-[[test-method]]
-== Testing Method Security
-
-This section demonstrates how to use Spring Security's Test support to test method based security.
-We first introduce a `MessageService` that requires the user to be authenticated in order to access it.
-
-[source,java]
-----
-public class HelloMessageService implements MessageService {
-
-	@PreAuthorize("authenticated")
-	public String getMessage() {
-		Authentication authentication = SecurityContextHolder.getContext()
-															.getAuthentication();
-		return "Hello " + authentication;
-	}
-}
-----
-
-The result of `getMessage` is a String saying "Hello" to the current Spring Security `Authentication`.
-An example of the output is displayed below.
-
-[source,text]
-----
-Hello org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ca25360: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER
-----
-
-[[test-method-setup]]
-=== Security Test Setup
-
-Before we can use Spring Security Test support, we must perform some setup. An example can be seen below:
-
-[source,java]
-----
-@RunWith(SpringJUnit4ClassRunner.class) // <1>
-@ContextConfiguration // <2>
-public class WithMockUserTests {
-----
-
-This is a basic example of how to setup Spring Security Test. The highlights are:
-
-<1> `@RunWith` instructs the spring-test module that it should create an `ApplicationContext`. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard[Spring Reference]
-<2> `@ContextConfiguration` instructs the spring-test the configuration to use to create the `ApplicationContext`. Since no configuration is specified, the default configuration locations will be tried. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#testcontext-ctx-management[Spring Reference]
-
-NOTE: Spring Security hooks into Spring Test support using the `WithSecurityContextTestExecutionListener` which will ensure our tests are ran with the correct user.
-It does this by populating the `SecurityContextHolder` prior to running our tests.
-After the test is done, it will clear out the `SecurityContextHolder`.
-If you only need Spring Security related support, you can replace `@ContextConfiguration` with `@SecurityTestExecutionListeners`.
-
-Remember we added the `@PreAuthorize` annotation to our `HelloMessageService` and so it requires an authenticated user to invoke it.
-If we ran the following test, we would expect the following test will pass:
-
-[source,java]
-----
-@Test(expected = AuthenticationCredentialsNotFoundException.class)
-public void getMessageUnauthenticated() {
-	messageService.getMessage();
-}
-----
-
-[[test-method-withmockuser]]
-=== @WithMockUser
-
-The question is "How could we most easily run the test as a specific user?"
-The answer is to use `@WithMockUser`.
-The following test will be run as a user with the username "user", the password "password", and the roles "ROLE_USER".
-
-[source,java]
-----
-@Test
-@WithMockUser
-public void getMessageWithMockUser() {
-String message = messageService.getMessage();
-...
-}
-----
-
-Specifically the following is true:
-
-* The user with the username "user" does not have to exist since we are mocking the user
-* The `Authentication` that is populated in the `SecurityContext` is of type `UsernamePasswordAuthenticationToken`
-* The principal on the `Authentication` is Spring Security's `User` object
-* The `User` will have the username of "user", the password "password", and a single `GrantedAuthority` named "ROLE_USER" is used.
-
-Our example is nice because we are able to leverage a lot of defaults.
-What if we wanted to run the test with a different username?
-The following test would run with the username "customUser". Again, the user does not need to actually exist.
-
-[source,java]
-----
-@Test
-@WithMockUser("customUsername")
-public void getMessageWithMockUserCustomUsername() {
-	String message = messageService.getMessage();
-...
-}
-----
-
-We can also easily customize the roles.
-For example, this test will be invoked with the username "admin" and the roles "ROLE_USER" and "ROLE_ADMIN".
-
-[source,java]
-----
-@Test
-@WithMockUser(username="admin",roles={"USER","ADMIN"})
-public void getMessageWithMockUserCustomUser() {
-	String message = messageService.getMessage();
-	...
-}
-----
-
-If we do not want the value to automatically be prefixed with ROLE_ we can leverage the authorities attribute.
-For example, this test will be invoked with the username "admin" and the authorities "USER" and "ADMIN".
-
-[source,java]
-----
-@Test
-@WithMockUser(username = "admin", authorities = { "ADMIN", "USER" })
-public void getMessageWithMockUserCustomAuthorities() {
-	String message = messageService.getMessage();
-	...
-}
-----
-
-Of course it can be a bit tedious placing the annotation on every test method.
-Instead, we can place the annotation at the class level and every test will use the specified user.
-For example, the following would run every test with a user with the username "admin", the password "password", and the roles "ROLE_USER" and "ROLE_ADMIN".
-
-[source,java]
-----
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration
-@WithMockUser(username="admin",roles={"USER","ADMIN"})
-public class WithMockUserTests {
-----
-
-By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
-This is the equivalent of happening before JUnit's `@Before`.
-You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
-
-[source,java]
-----
-@WithMockUser(setupBefore = TestExecutionEvent.TEST_EXECUTION)
-----
-
-
-[[test-method-withanonymoususer]]
-=== @WithAnonymousUser
-
-Using `@WithAnonymousUser` allows running as an anonymous user.
-This is especially convenient when you wish to run most of your tests with a specific user, but want to run a few tests as an anonymous user.
-For example, the following will run withMockUser1 and withMockUser2 using <<test-method-withmockuser,@WithMockUser>> and anonymous as an anonymous user.
-
-[source,java]
-----
-@RunWith(SpringJUnit4ClassRunner.class)
-@WithMockUser
-public class WithUserClassLevelAuthenticationTests {
-
-	@Test
-	public void withMockUser1() {
-	}
-
-	@Test
-	public void withMockUser2() {
-	}
-
-	@Test
-	@WithAnonymousUser
-	public void anonymous() throws Exception {
-		// override default to run as anonymous user
-	}
-}
-----
-
-By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
-This is the equivalent of happening before JUnit's `@Before`.
-You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
-
-[source,java]
-----
-@WithAnonymousUser(setupBefore = TestExecutionEvent.TEST_EXECUTION)
-----
-
-
-[[test-method-withuserdetails]]
-=== @WithUserDetails
-
-While `@WithMockUser` is a very convenient way to get started, it may not work in all instances.
-For example, it is common for applications to expect that the `Authentication` principal be of a specific type.
-This is done so that the application can refer to the principal as the custom type and reduce coupling on Spring Security.
-
-The custom principal is often times returned by a custom `UserDetailsService` that returns an object that implements both `UserDetails` and the custom type.
-For situations like this, it is useful to create the test user using the custom `UserDetailsService`.
-That is exactly what `@WithUserDetails` does.
-
-Assuming we have a `UserDetailsService` exposed as a bean, the following test will be invoked with an `Authentication` of type `UsernamePasswordAuthenticationToken` and a principal that is returned from the `UserDetailsService` with the username of "user".
-
-[source,java]
-----
-@Test
-@WithUserDetails
-public void getMessageWithUserDetails() {
-	String message = messageService.getMessage();
-	...
-}
-----
-
-We can also customize the username used to lookup the user from our `UserDetailsService`.
-For example, this test would be executed with a principal that is returned from the `UserDetailsService` with the username of "customUsername".
-
-[source,java]
-----
-@Test
-@WithUserDetails("customUsername")
-public void getMessageWithUserDetailsCustomUsername() {
-	String message = messageService.getMessage();
-	...
-}
-----
-
-We can also provide an explicit bean name to look up the `UserDetailsService`.
-For example, this test would look up the username of "customUsername" using the `UserDetailsService` with the bean name "myUserDetailsService".
-
-[source,java]
-----
-@Test
-@WithUserDetails(value="customUsername", userDetailsServiceBeanName="myUserDetailsService")
-public void getMessageWithUserDetailsServiceBeanName() {
-	String message = messageService.getMessage();
-	...
-}
-----
-
-Like `@WithMockUser` we can also place our annotation at the class level so that every test uses the same user.
-However unlike `@WithMockUser`, `@WithUserDetails` requires the user to exist.
-
-By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
-This is the equivalent of happening before JUnit's `@Before`.
-You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
-
-[source,java]
-----
-@WithUserDetails(setupBefore = TestExecutionEvent.TEST_EXECUTION)
-----
-
-
-[[test-method-withsecuritycontext]]
-=== @WithSecurityContext
-
-We have seen that `@WithMockUser` is an excellent choice if we are not using a custom `Authentication` principal.
-Next we discovered that `@WithUserDetails` would allow us to use a custom `UserDetailsService` to create our `Authentication` principal but required the user to exist.
-We will now see an option that allows the most flexibility.
-
-We can create our own annotation that uses the `@WithSecurityContext` to create any `SecurityContext` we want.
-For example, we might create an annotation named `@WithMockCustomUser` as shown below:
-
-[source,java]
-----
-@Retention(RetentionPolicy.RUNTIME)
-@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
-public @interface WithMockCustomUser {
-
-	String username() default "rob";
-
-	String name() default "Rob Winch";
-}
-----
-
-You can see that `@WithMockCustomUser` is annotated with the `@WithSecurityContext` annotation.
-This is what signals to Spring Security Test support that we intend to create a `SecurityContext` for the test.
-The `@WithSecurityContext` annotation requires we specify a `SecurityContextFactory` that will create a new `SecurityContext` given our `@WithMockCustomUser` annotation.
-You can find our `WithMockCustomUserSecurityContextFactory` implementation below:
-
-[source,java]
-----
-public class WithMockCustomUserSecurityContextFactory
-	implements WithSecurityContextFactory<WithMockCustomUser> {
-	@Override
-	public SecurityContext createSecurityContext(WithMockCustomUser customUser) {
-		SecurityContext context = SecurityContextHolder.createEmptyContext();
-
-		CustomUserDetails principal =
-			new CustomUserDetails(customUser.name(), customUser.username());
-		Authentication auth =
-			new UsernamePasswordAuthenticationToken(principal, "password", principal.getAuthorities());
-		context.setAuthentication(auth);
-		return context;
-	}
-}
-----
-
-We can now annotate a test class or a test method with our new annotation and Spring Security's `WithSecurityContextTestExecutionListener` will ensure that our `SecurityContext` is populated appropriately.
-
-When creating your own `WithSecurityContextFactory` implementations, it is nice to know that they can be annotated with standard Spring annotations.
-For example, the `WithUserDetailsSecurityContextFactory` uses the `@Autowired` annotation to acquire the `UserDetailsService`:
-
-[source,java]
-----
-final class WithUserDetailsSecurityContextFactory
-	implements WithSecurityContextFactory<WithUserDetails> {
-
-	private UserDetailsService userDetailsService;
-
-	@Autowired
-	public WithUserDetailsSecurityContextFactory(UserDetailsService userDetailsService) {
-		this.userDetailsService = userDetailsService;
-	}
-
-	public SecurityContext createSecurityContext(WithUserDetails withUser) {
-		String username = withUser.value();
-		Assert.hasLength(username, "value() must be non-empty String");
-		UserDetails principal = userDetailsService.loadUserByUsername(username);
-		Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
-		SecurityContext context = SecurityContextHolder.createEmptyContext();
-		context.setAuthentication(authentication);
-		return context;
-	}
-}
-----
-
-By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
-This is the equivalent of happening before JUnit's `@Before`.
-You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
-
-[source,java]
-----
-@WithSecurityContext(setupBefore = TestExecutionEvent.TEST_EXECUTION)
-----
-
-
-[[test-method-meta-annotations]]
-=== Test Meta Annotations
-
-If you reuse the same user within your tests often, it is not ideal to have to repeatedly specify the attributes.
-For example, if there are many tests related to an administrative user with the username "admin" and the roles `ROLE_USER` and `ROLE_ADMIN` you would have to write:
-
-[source,java]
-----
-@WithMockUser(username="admin",roles={"USER","ADMIN"})
-----
-
-Rather than repeating this everywhere, we can use a meta annotation.
-For example, we could create a meta annotation named `WithMockAdmin`:
-
-[source,java]
-----
-@Retention(RetentionPolicy.RUNTIME)
-@WithMockUser(value="rob",roles="ADMIN")
-public @interface WithMockAdmin { }
-----
-
-Now we can use `@WithMockAdmin` in the same way as the more verbose `@WithMockUser`.
-
-Meta annotations work with any of the testing annotations described above.
-For example, this means we could create a meta annotation for `@WithUserDetails("admin")` as well.
-
-
-[[test-mockmvc]]
-== Spring MVC Test Integration
-
-Spring Security provides comprehensive integration with http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework[Spring MVC Test]
-
-[[test-mockmvc-setup]]
-=== Setting Up MockMvc and Spring Security
-
-In order to use Spring Security with Spring MVC Test it is necessary to add the Spring Security `FilterChainProxy` as a `Filter`.
-It is also necessary to add Spring Security's `TestSecurityContextHolderPostProcessor` to support <<Running as a User in Spring MVC Test with Annotations,Running as a User in Spring MVC Test with Annotations>>.
-This can be done using Spring Security's `SecurityMockMvcConfigurers.springSecurity()`.
-For example:
-
-NOTE: Spring Security's testing support requires spring-test-4.1.3.RELEASE or greater.
-
-[source,java]
-----
-
-import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration
-@WebAppConfiguration
-public class CsrfShowcaseTests {
-
-	@Autowired
-	private WebApplicationContext context;
-
-	private MockMvc mvc;
-
-	@Before
-	public void setup() {
-		mvc = MockMvcBuilders
-				.webAppContextSetup(context)
-				.apply(springSecurity()) // <1>
-				.build();
-	}
-
-...
-----
-
-<1> `SecurityMockMvcConfigurers.springSecurity()` will perform all of the initial setup we need to integrate Spring Security with Spring MVC Test
-
-[[test-mockmvc-smmrpp]]
-=== SecurityMockMvcRequestPostProcessors
-
-Spring MVC Test provides a convenient interface called a `RequestPostProcessor` that can be used to modify a request.
-Spring Security provides a number of `RequestPostProcessor` implementations that make testing easier.
-In order to use Spring Security's `RequestPostProcessor` implementations ensure the following static import is used:
-
-[source,java]
-----
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
-----
-
-[[test-mockmvc-csrf]]
-==== Testing with CSRF Protection
-
-When testing any non-safe HTTP methods and using Spring Security's CSRF protection, you must be sure to include a valid CSRF Token in the request.
-To specify a valid CSRF token as a request parameter using the following:
-
-[source,java]
-----
-mvc
-	.perform(post("/").with(csrf()))
-----
-
-If you like you can include CSRF token in the header instead:
-
-[source,java]
-----
-mvc
-	.perform(post("/").with(csrf().asHeader()))
-----
-
-You can also test providing an invalid CSRF token using the following:
-
-[source,java]
-----
-mvc
-	.perform(post("/").with(csrf().useInvalidToken()))
-----
-
-[[test-mockmvc-securitycontextholder]]
-==== Running a Test as a User in Spring MVC Test
-
-It is often desirable to run tests as a specific user.
-There are two simple ways of populating the user:
-
-* <<Running as a User in Spring MVC Test with RequestPostProcessor,Running as a User in Spring MVC Test with RequestPostProcessor>>
-* <<Running as a User in Spring MVC Test with Annotations,Running as a User in Spring MVC Test with Annotations>>
-
-[[test-mockmvc-securitycontextholder-rpp]]
-==== Running as a User in Spring MVC Test with RequestPostProcessor
-
-There are a number of options available to associate a user to the current `HttpServletRequest`.
-For example, the following will run as a user (which does not need to exist) with the username "user", the password "password", and the role "ROLE_USER":
-
-[NOTE]
-====
-The support works by associating the user to the `HttpServletRequest`.
-To associate the request to the `SecurityContextHolder` you need to ensure that the `SecurityContextPersistenceFilter` is associated with the `MockMvc` instance.
-A few ways to do this are:
-
-* Invoking <<test-mockmvc-setup,apply(springSecurity())>>
-* Adding Spring Security's `FilterChainProxy` to `MockMvc`
-* Manually adding `SecurityContextPersistenceFilter` to the `MockMvc` instance may make sense when using `MockMvcBuilders.standaloneSetup`
-====
-
-[source,java]
-----
-mvc
-	.perform(get("/").with(user("user")))
-----
-
-You can easily make customizations.
-For example, the following will run as a user (which does not need to exist) with the username "admin", the password "pass", and the roles "ROLE_USER" and "ROLE_ADMIN".
-
-[source,java]
-----
-mvc
-	.perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
-----
-
-If you have a custom `UserDetails` that you would like to use, you can easily specify that as well.
-For example, the following will use the specified `UserDetails` (which does not need to exist) to run with a `UsernamePasswordAuthenticationToken` that has a principal of the specified `UserDetails`:
-
-[source,java]
-----
-mvc
-	.perform(get("/").with(user(userDetails)))
-----
-
-You can run as anonymous user using the following:
-
-[source,java]
-----
-mvc
-	.perform(get("/").with(anonymous()))
-----
-
-This is especially useful if you are running with a default user and wish to execute a few requests as an anonymous user.
-
-If you want a custom `Authentication` (which does not need to exist) you can do so using the following:
-
-[source,java]
-----
-mvc
-	.perform(get("/").with(authentication(authentication)))
-----
-
-You can even customize the `SecurityContext` using the following:
-
-[source,java]
-----
-mvc
-	.perform(get("/").with(securityContext(securityContext)))
-----
-
-We can also ensure to run as a specific user for every request by using ``MockMvcBuilders``'s default request.
-For example, the following will run as a user (which does not need to exist) with the username "admin", the password "password", and the role "ROLE_ADMIN":
-
-[source,java]
-----
-mvc = MockMvcBuilders
-		.webAppContextSetup(context)
-		.defaultRequest(get("/").with(user("user").roles("ADMIN")))
-		.apply(springSecurity())
-		.build();
-----
-
-If you find you are using the same user in many of your tests, it is recommended to move the user to a method.
-For example, you can specify the following in your own class named `CustomSecurityMockMvcRequestPostProcessors`:
-
-[source,java]
-----
-public static RequestPostProcessor rob() {
-	return user("rob").roles("ADMIN");
-}
-----
-
-Now you can perform a static import on `SecurityMockMvcRequestPostProcessors` and use that within your tests:
-
-[source,java]
-----
-import static sample.CustomSecurityMockMvcRequestPostProcessors.*;
-
-...
-
-mvc
-	.perform(get("/").with(rob()))
-----
-
-===== Running as a User in Spring MVC Test with Annotations
-
-As an alternative to using a `RequestPostProcessor` to create your user, you can use annotations described in <<Testing Method Security>>.
-For example, the following will run the test with the user with username "user", password "password", and role "ROLE_USER":
-
-[source,java]
-----
-@Test
-@WithMockUser
-public void requestProtectedUrlWithUser() throws Exception {
-mvc
-		.perform(get("/"))
-		...
-}
-----
-
-Alternatively, the following will run the test with the user with username "user", password "password", and role "ROLE_ADMIN":
-
-[source,java]
-----
-@Test
-@WithMockUser(roles="ADMIN")
-public void requestProtectedUrlWithUser() throws Exception {
-mvc
-		.perform(get("/"))
-		...
-}
-----
-
-==== Testing HTTP Basic Authentication
-
-While it has always been possible to authenticate with HTTP Basic, it was a bit tedious to remember the header name, format, and encode the values.
-Now this can be done using Spring Security's `httpBasic` `RequestPostProcessor`.
-For example, the snippet below:
-
-[source,java]
-----
-mvc
-	.perform(get("/").with(httpBasic("user","password")))
-----
-
-will attempt to use HTTP Basic to authenticate a user with the username "user" and the password "password" by ensuring the following header is populated on the HTTP Request:
-
-[source,text]
-----
-Authorization: Basic dXNlcjpwYXNzd29yZA==
-----
-
-=== SecurityMockMvcRequestBuilders
-
-Spring MVC Test also provides a `RequestBuilder` interface that can be used to create the `MockHttpServletRequest` used in your test.
-Spring Security provides a few `RequestBuilder` implementations that can be used to make testing easier.
-In order to use Spring Security's `RequestBuilder` implementations ensure the following static import is used:
-
-[source,java]
-----
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
-----
-
-==== Testing Form Based Authentication
-
-You can easily create a request to test a form based authentication using Spring Security's testing support.
-For example, the following will submit a POST to "/login" with the username "user", the password "password", and a valid CSRF token:
-
-[source,java]
-----
-mvc
-	.perform(formLogin())
-----
-
-It is easy to customize the request.
-For example, the following will submit a POST to "/auth" with the username "admin", the password "pass", and a valid CSRF token:
-
-[source,java]
-----
-mvc
-	.perform(formLogin("/auth").user("admin").password("pass"))
-----
-
-We can also customize the parameters names that the username and password are included on.
-For example, this is the above request modified to include the username on the HTTP parameter "u" and the password on the HTTP parameter "p".
-
-[source,java]
-----
-mvc
-	.perform(formLogin("/auth").user("u","admin").password("p","pass"))
-----
-
-[[test-logout]]
-==== Testing Logout
-
-While fairly trivial using standard Spring MVC Test, you can use Spring Security's testing support to make testing log out easier.
-For example, the following will submit a POST to "/logout" with a valid CSRF token:
-
-[source,java]
-----
-mvc
-	.perform(logout())
-----
-
-You can also customize the URL to post to.
-For example, the snippet below will submit a POST to "/signout" with a valid CSRF token:
-
-[source,java]
-----
-mvc
-	.perform(logout("/signout"))
-----
-
-=== SecurityMockMvcResultMatchers
-
-At times it is desirable to make various security related assertions about a request.
-To accommodate this need, Spring Security Test support implements Spring MVC Test's `ResultMatcher` interface.
-In order to use Spring Security's `ResultMatcher` implementations ensure the following static import is used:
-
-[source,java]
-----
-import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*;
-----
-
-==== Unauthenticated Assertion
-
-At times it may be valuable to assert that there is no authenticated user associated with the result of a `MockMvc` invocation.
-For example, you might want to test submitting an invalid username and password and verify that no user is authenticated.
-You can easily do this with Spring Security's testing support using something like the following:
-
-[source,java]
-----
-mvc
-	.perform(formLogin().password("invalid"))
-	.andExpect(unauthenticated());
-----
-
-==== Authenticated Assertion
-
-It is often times that we must assert that an authenticated user exists.
-For example, we may want to verify that we authenticated successfully.
-We could verify that a form based login was successful with the following snippet of code:
-
-[source,java]
-----
-mvc
-	.perform(formLogin())
-	.andExpect(authenticated());
-----
-
-If we wanted to assert the roles of the user, we could refine our previous code as shown below:
-
-[source,java]
-----
-mvc
-	.perform(formLogin().user("admin"))
-	.andExpect(authenticated().withRoles("USER","ADMIN"));
-----
-
-Alternatively, we could verify the username:
-
-[source,java]
-----
-mvc
-	.perform(formLogin().user("admin"))
-	.andExpect(authenticated().withUsername("admin"));
-----
-
-We can also combine the assertions:
-
-[source,java]
-----
-mvc
-	.perform(formLogin().user("admin").roles("USER","ADMIN"))
-	.andExpect(authenticated().withUsername("admin"));
-----
-
-We can also make arbitrary assertions on the authentication
-
-[source,java]
-----
-mvc
-	.perform(formLogin())
-	.andExpect(authenticated().withAuthentication(auth ->
-		assertThat(auth).isInstanceOf(UsernamePasswordAuthenticationToken.class)));
-----
-
-[[test-webflux]]
-== WebFlux Support
-
-Spring Security provides test integration with Spring WebFlux for both method security and WebFlux.
-You can find a complete working sample at {gh-samples-url}/javaconfig/hellowebflux-method[hellowebflux-method]
-
-
-[[test-erms]]
-=== Reactive Method Security
-
-For example, we can test our example from <<jc-erms>> using the same setup and annotations we did in <<test-method>>.
-Here is a minimal sample of what we can do:
-
-[source,java]
-----
-@RunWith(SpringRunner.class)
-@ContextConfiguration(classes = HelloWebfluxMethodApplication.class)
-public class HelloWorldMessageServiceTests {
-	@Autowired
-	HelloWorldMessageService messages;
-
-	@Test
-	public void messagesWhenNotAuthenticatedThenDenied() {
-		StepVerifier.create(this.messages.findMessage())
-			.expectError(AccessDeniedException.class)
-			.verify();
-	}
-
-	@Test
-	@WithMockUser
-	public void messagesWhenUserThenDenied() {
-		StepVerifier.create(this.messages.findMessage())
-			.expectError(AccessDeniedException.class)
-			.verify();
-	}
-
-	@Test
-	@WithMockUser(roles = "ADMIN")
-	public void messagesWhenAdminThenOk() {
-		StepVerifier.create(this.messages.findMessage())
-			.expectNext("Hello World!")
-			.verifyComplete();
-	}
-}
-----
-
-[[test-webtestclient]]
-=== WebTestClientSupport
-
-Spring Security provides integration with `WebTestClient`.
-The basic setup looks like this:
-
-[source,java]
-----
-@RunWith(SpringRunner.class)
-@ContextConfiguration(classes = HelloWebfluxMethodApplication.class)
-public class HelloWebfluxMethodApplicationTests {
-	@Autowired
-	ApplicationContext context;
-
-	WebTestClient rest;
-
-	@Before
-	public void setup() {
-		this.rest = WebTestClient
-			.bindToApplicationContext(this.context)
-			// add Spring Security test Support
-			.apply(springSecurity())
-			.configureClient()
-			.filter(basicAuthentication())
-			.build();
-	}
-	// ...
-}
-----
-
-==== Authentication
-
-After applying the Spring Security support to `WebTestClient` we can use either annotations or `mutateWith` support.
-For example:
-
-[source,java]
-----
-@Test
-public void messageWhenNotAuthenticated() throws Exception {
-	this.rest
-		.get()
-		.uri("/message")
-		.exchange()
-		.expectStatus().isUnauthorized();
-}
-
-// --- WithMockUser ---
-
-@Test
-@WithMockUser
-public void messageWhenWithMockUserThenForbidden() throws Exception {
-	this.rest
-		.get()
-		.uri("/message")
-		.exchange()
-		.expectStatus().isEqualTo(HttpStatus.FORBIDDEN);
-}
-
-@Test
-@WithMockUser(roles = "ADMIN")
-public void messageWhenWithMockAdminThenOk() throws Exception {
-	this.rest
-		.get()
-		.uri("/message")
-		.exchange()
-		.expectStatus().isOk()
-		.expectBody(String.class).isEqualTo("Hello World!");
-}
-
-// --- mutateWith mockUser ---
-
-@Test
-public void messageWhenMutateWithMockUserThenForbidden() throws Exception {
-	this.rest
-		.mutateWith(mockUser())
-		.get()
-		.uri("/message")
-		.exchange()
-		.expectStatus().isEqualTo(HttpStatus.FORBIDDEN);
-}
-
-@Test
-public void messageWhenMutateWithMockAdminThenOk() throws Exception {
-	this.rest
-		.mutateWith(mockUser().roles("ADMIN"))
-		.get()
-		.uri("/message")
-		.exchange()
-		.expectStatus().isOk()
-		.expectBody(String.class).isEqualTo("Hello World!");
-}
-----
-
-
-==== CSRF Support
-
-Spring Security also provides support for CSRF testing with `WebTestClient`.
-For example:
-
-[source,java]
-----
-this.rest
-	// provide a valid CSRF token
-	.mutateWith(csrf())
-	.post()
-	.uri("/login")
-	...
-----

+ 15 - 0
docs/manual/src/docs/asciidoc/_includes/test/index.adoc

@@ -0,0 +1,15 @@
+[[test]]
+= Testing
+
+This section describes the testing support provided by Spring Security.
+
+[TIP]
+====
+To use the Spring Security test support, you must include `spring-security-test-{spring-security-version}.jar` as a dependency of your project.
+====
+
+include::method.adoc[]
+
+include::mockmvc.adoc[]
+
+include::webtestclient.adoc[]

+ 356 - 0
docs/manual/src/docs/asciidoc/_includes/test/method.adoc

@@ -0,0 +1,356 @@
+[[test-method]]
+== Testing Method Security
+
+This section demonstrates how to use Spring Security's Test support to test method based security.
+We first introduce a `MessageService` that requires the user to be authenticated in order to access it.
+
+[source,java]
+----
+public class HelloMessageService implements MessageService {
+
+	@PreAuthorize("authenticated")
+	public String getMessage() {
+		Authentication authentication = SecurityContextHolder.getContext()
+															.getAuthentication();
+		return "Hello " + authentication;
+	}
+}
+----
+
+The result of `getMessage` is a String saying "Hello" to the current Spring Security `Authentication`.
+An example of the output is displayed below.
+
+[source,text]
+----
+Hello org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ca25360: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER
+----
+
+[[test-method-setup]]
+=== Security Test Setup
+
+Before we can use Spring Security Test support, we must perform some setup. An example can be seen below:
+
+[source,java]
+----
+@RunWith(SpringJUnit4ClassRunner.class) // <1>
+@ContextConfiguration // <2>
+public class WithMockUserTests {
+----
+
+This is a basic example of how to setup Spring Security Test. The highlights are:
+
+<1> `@RunWith` instructs the spring-test module that it should create an `ApplicationContext`. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard[Spring Reference]
+<2> `@ContextConfiguration` instructs the spring-test the configuration to use to create the `ApplicationContext`. Since no configuration is specified, the default configuration locations will be tried. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#testcontext-ctx-management[Spring Reference]
+
+NOTE: Spring Security hooks into Spring Test support using the `WithSecurityContextTestExecutionListener` which will ensure our tests are ran with the correct user.
+It does this by populating the `SecurityContextHolder` prior to running our tests.
+After the test is done, it will clear out the `SecurityContextHolder`.
+If you only need Spring Security related support, you can replace `@ContextConfiguration` with `@SecurityTestExecutionListeners`.
+
+Remember we added the `@PreAuthorize` annotation to our `HelloMessageService` and so it requires an authenticated user to invoke it.
+If we ran the following test, we would expect the following test will pass:
+
+[source,java]
+----
+@Test(expected = AuthenticationCredentialsNotFoundException.class)
+public void getMessageUnauthenticated() {
+	messageService.getMessage();
+}
+----
+
+[[test-method-withmockuser]]
+=== @WithMockUser
+
+The question is "How could we most easily run the test as a specific user?"
+The answer is to use `@WithMockUser`.
+The following test will be run as a user with the username "user", the password "password", and the roles "ROLE_USER".
+
+[source,java]
+----
+@Test
+@WithMockUser
+public void getMessageWithMockUser() {
+String message = messageService.getMessage();
+...
+}
+----
+
+Specifically the following is true:
+
+* The user with the username "user" does not have to exist since we are mocking the user
+* The `Authentication` that is populated in the `SecurityContext` is of type `UsernamePasswordAuthenticationToken`
+* The principal on the `Authentication` is Spring Security's `User` object
+* The `User` will have the username of "user", the password "password", and a single `GrantedAuthority` named "ROLE_USER" is used.
+
+Our example is nice because we are able to leverage a lot of defaults.
+What if we wanted to run the test with a different username?
+The following test would run with the username "customUser". Again, the user does not need to actually exist.
+
+[source,java]
+----
+@Test
+@WithMockUser("customUsername")
+public void getMessageWithMockUserCustomUsername() {
+	String message = messageService.getMessage();
+...
+}
+----
+
+We can also easily customize the roles.
+For example, this test will be invoked with the username "admin" and the roles "ROLE_USER" and "ROLE_ADMIN".
+
+[source,java]
+----
+@Test
+@WithMockUser(username="admin",roles={"USER","ADMIN"})
+public void getMessageWithMockUserCustomUser() {
+	String message = messageService.getMessage();
+	...
+}
+----
+
+If we do not want the value to automatically be prefixed with ROLE_ we can leverage the authorities attribute.
+For example, this test will be invoked with the username "admin" and the authorities "USER" and "ADMIN".
+
+[source,java]
+----
+@Test
+@WithMockUser(username = "admin", authorities = { "ADMIN", "USER" })
+public void getMessageWithMockUserCustomAuthorities() {
+	String message = messageService.getMessage();
+	...
+}
+----
+
+Of course it can be a bit tedious placing the annotation on every test method.
+Instead, we can place the annotation at the class level and every test will use the specified user.
+For example, the following would run every test with a user with the username "admin", the password "password", and the roles "ROLE_USER" and "ROLE_ADMIN".
+
+[source,java]
+----
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+@WithMockUser(username="admin",roles={"USER","ADMIN"})
+public class WithMockUserTests {
+----
+
+By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
+This is the equivalent of happening before JUnit's `@Before`.
+You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
+
+[source,java]
+----
+@WithMockUser(setupBefore = TestExecutionEvent.TEST_EXECUTION)
+----
+
+
+[[test-method-withanonymoususer]]
+=== @WithAnonymousUser
+
+Using `@WithAnonymousUser` allows running as an anonymous user.
+This is especially convenient when you wish to run most of your tests with a specific user, but want to run a few tests as an anonymous user.
+For example, the following will run withMockUser1 and withMockUser2 using <<test-method-withmockuser,@WithMockUser>> and anonymous as an anonymous user.
+
+[source,java]
+----
+@RunWith(SpringJUnit4ClassRunner.class)
+@WithMockUser
+public class WithUserClassLevelAuthenticationTests {
+
+	@Test
+	public void withMockUser1() {
+	}
+
+	@Test
+	public void withMockUser2() {
+	}
+
+	@Test
+	@WithAnonymousUser
+	public void anonymous() throws Exception {
+		// override default to run as anonymous user
+	}
+}
+----
+
+By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
+This is the equivalent of happening before JUnit's `@Before`.
+You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
+
+[source,java]
+----
+@WithAnonymousUser(setupBefore = TestExecutionEvent.TEST_EXECUTION)
+----
+
+
+[[test-method-withuserdetails]]
+=== @WithUserDetails
+
+While `@WithMockUser` is a very convenient way to get started, it may not work in all instances.
+For example, it is common for applications to expect that the `Authentication` principal be of a specific type.
+This is done so that the application can refer to the principal as the custom type and reduce coupling on Spring Security.
+
+The custom principal is often times returned by a custom `UserDetailsService` that returns an object that implements both `UserDetails` and the custom type.
+For situations like this, it is useful to create the test user using the custom `UserDetailsService`.
+That is exactly what `@WithUserDetails` does.
+
+Assuming we have a `UserDetailsService` exposed as a bean, the following test will be invoked with an `Authentication` of type `UsernamePasswordAuthenticationToken` and a principal that is returned from the `UserDetailsService` with the username of "user".
+
+[source,java]
+----
+@Test
+@WithUserDetails
+public void getMessageWithUserDetails() {
+	String message = messageService.getMessage();
+	...
+}
+----
+
+We can also customize the username used to lookup the user from our `UserDetailsService`.
+For example, this test would be executed with a principal that is returned from the `UserDetailsService` with the username of "customUsername".
+
+[source,java]
+----
+@Test
+@WithUserDetails("customUsername")
+public void getMessageWithUserDetailsCustomUsername() {
+	String message = messageService.getMessage();
+	...
+}
+----
+
+We can also provide an explicit bean name to look up the `UserDetailsService`.
+For example, this test would look up the username of "customUsername" using the `UserDetailsService` with the bean name "myUserDetailsService".
+
+[source,java]
+----
+@Test
+@WithUserDetails(value="customUsername", userDetailsServiceBeanName="myUserDetailsService")
+public void getMessageWithUserDetailsServiceBeanName() {
+	String message = messageService.getMessage();
+	...
+}
+----
+
+Like `@WithMockUser` we can also place our annotation at the class level so that every test uses the same user.
+However unlike `@WithMockUser`, `@WithUserDetails` requires the user to exist.
+
+By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
+This is the equivalent of happening before JUnit's `@Before`.
+You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
+
+[source,java]
+----
+@WithUserDetails(setupBefore = TestExecutionEvent.TEST_EXECUTION)
+----
+
+
+[[test-method-withsecuritycontext]]
+=== @WithSecurityContext
+
+We have seen that `@WithMockUser` is an excellent choice if we are not using a custom `Authentication` principal.
+Next we discovered that `@WithUserDetails` would allow us to use a custom `UserDetailsService` to create our `Authentication` principal but required the user to exist.
+We will now see an option that allows the most flexibility.
+
+We can create our own annotation that uses the `@WithSecurityContext` to create any `SecurityContext` we want.
+For example, we might create an annotation named `@WithMockCustomUser` as shown below:
+
+[source,java]
+----
+@Retention(RetentionPolicy.RUNTIME)
+@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
+public @interface WithMockCustomUser {
+
+	String username() default "rob";
+
+	String name() default "Rob Winch";
+}
+----
+
+You can see that `@WithMockCustomUser` is annotated with the `@WithSecurityContext` annotation.
+This is what signals to Spring Security Test support that we intend to create a `SecurityContext` for the test.
+The `@WithSecurityContext` annotation requires we specify a `SecurityContextFactory` that will create a new `SecurityContext` given our `@WithMockCustomUser` annotation.
+You can find our `WithMockCustomUserSecurityContextFactory` implementation below:
+
+[source,java]
+----
+public class WithMockCustomUserSecurityContextFactory
+	implements WithSecurityContextFactory<WithMockCustomUser> {
+	@Override
+	public SecurityContext createSecurityContext(WithMockCustomUser customUser) {
+		SecurityContext context = SecurityContextHolder.createEmptyContext();
+
+		CustomUserDetails principal =
+			new CustomUserDetails(customUser.name(), customUser.username());
+		Authentication auth =
+			new UsernamePasswordAuthenticationToken(principal, "password", principal.getAuthorities());
+		context.setAuthentication(auth);
+		return context;
+	}
+}
+----
+
+We can now annotate a test class or a test method with our new annotation and Spring Security's `WithSecurityContextTestExecutionListener` will ensure that our `SecurityContext` is populated appropriately.
+
+When creating your own `WithSecurityContextFactory` implementations, it is nice to know that they can be annotated with standard Spring annotations.
+For example, the `WithUserDetailsSecurityContextFactory` uses the `@Autowired` annotation to acquire the `UserDetailsService`:
+
+[source,java]
+----
+final class WithUserDetailsSecurityContextFactory
+	implements WithSecurityContextFactory<WithUserDetails> {
+
+	private UserDetailsService userDetailsService;
+
+	@Autowired
+	public WithUserDetailsSecurityContextFactory(UserDetailsService userDetailsService) {
+		this.userDetailsService = userDetailsService;
+	}
+
+	public SecurityContext createSecurityContext(WithUserDetails withUser) {
+		String username = withUser.value();
+		Assert.hasLength(username, "value() must be non-empty String");
+		UserDetails principal = userDetailsService.loadUserByUsername(username);
+		Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
+		SecurityContext context = SecurityContextHolder.createEmptyContext();
+		context.setAuthentication(authentication);
+		return context;
+	}
+}
+----
+
+By default the `SecurityContext` is set during the `TestExecutionListener.beforeTestMethod` event.
+This is the equivalent of happening before JUnit's `@Before`.
+You can change this to happen during the `TestExecutionListener.beforeTestExecution` event which is after JUnit's `@Before` but before the test method is invoked.
+
+[source,java]
+----
+@WithSecurityContext(setupBefore = TestExecutionEvent.TEST_EXECUTION)
+----
+
+
+[[test-method-meta-annotations]]
+=== Test Meta Annotations
+
+If you reuse the same user within your tests often, it is not ideal to have to repeatedly specify the attributes.
+For example, if there are many tests related to an administrative user with the username "admin" and the roles `ROLE_USER` and `ROLE_ADMIN` you would have to write:
+
+[source,java]
+----
+@WithMockUser(username="admin",roles={"USER","ADMIN"})
+----
+
+Rather than repeating this everywhere, we can use a meta annotation.
+For example, we could create a meta annotation named `WithMockAdmin`:
+
+[source,java]
+----
+@Retention(RetentionPolicy.RUNTIME)
+@WithMockUser(value="rob",roles="ADMIN")
+public @interface WithMockAdmin { }
+----
+
+Now we can use `@WithMockAdmin` in the same way as the more verbose `@WithMockUser`.
+
+Meta annotations work with any of the testing annotations described above.
+For example, this means we could create a meta annotation for `@WithUserDetails("admin")` as well.

+ 376 - 0
docs/manual/src/docs/asciidoc/_includes/test/mockmvc.adoc

@@ -0,0 +1,376 @@
+
+[[test-mockmvc]]
+== Spring MVC Test Integration
+
+Spring Security provides comprehensive integration with http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework[Spring MVC Test]
+
+[[test-mockmvc-setup]]
+=== Setting Up MockMvc and Spring Security
+
+In order to use Spring Security with Spring MVC Test it is necessary to add the Spring Security `FilterChainProxy` as a `Filter`.
+It is also necessary to add Spring Security's `TestSecurityContextHolderPostProcessor` to support <<Running as a User in Spring MVC Test with Annotations,Running as a User in Spring MVC Test with Annotations>>.
+This can be done using Spring Security's `SecurityMockMvcConfigurers.springSecurity()`.
+For example:
+
+NOTE: Spring Security's testing support requires spring-test-4.1.3.RELEASE or greater.
+
+[source,java]
+----
+
+import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+@WebAppConfiguration
+public class CsrfShowcaseTests {
+
+	@Autowired
+	private WebApplicationContext context;
+
+	private MockMvc mvc;
+
+	@Before
+	public void setup() {
+		mvc = MockMvcBuilders
+				.webAppContextSetup(context)
+				.apply(springSecurity()) // <1>
+				.build();
+	}
+
+...
+----
+
+<1> `SecurityMockMvcConfigurers.springSecurity()` will perform all of the initial setup we need to integrate Spring Security with Spring MVC Test
+
+[[test-mockmvc-smmrpp]]
+=== SecurityMockMvcRequestPostProcessors
+
+Spring MVC Test provides a convenient interface called a `RequestPostProcessor` that can be used to modify a request.
+Spring Security provides a number of `RequestPostProcessor` implementations that make testing easier.
+In order to use Spring Security's `RequestPostProcessor` implementations ensure the following static import is used:
+
+[source,java]
+----
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
+----
+
+[[test-mockmvc-csrf]]
+==== Testing with CSRF Protection
+
+When testing any non-safe HTTP methods and using Spring Security's CSRF protection, you must be sure to include a valid CSRF Token in the request.
+To specify a valid CSRF token as a request parameter using the following:
+
+[source,java]
+----
+mvc
+	.perform(post("/").with(csrf()))
+----
+
+If you like you can include CSRF token in the header instead:
+
+[source,java]
+----
+mvc
+	.perform(post("/").with(csrf().asHeader()))
+----
+
+You can also test providing an invalid CSRF token using the following:
+
+[source,java]
+----
+mvc
+	.perform(post("/").with(csrf().useInvalidToken()))
+----
+
+[[test-mockmvc-securitycontextholder]]
+==== Running a Test as a User in Spring MVC Test
+
+It is often desirable to run tests as a specific user.
+There are two simple ways of populating the user:
+
+* <<Running as a User in Spring MVC Test with RequestPostProcessor,Running as a User in Spring MVC Test with RequestPostProcessor>>
+* <<Running as a User in Spring MVC Test with Annotations,Running as a User in Spring MVC Test with Annotations>>
+
+[[test-mockmvc-securitycontextholder-rpp]]
+==== Running as a User in Spring MVC Test with RequestPostProcessor
+
+There are a number of options available to associate a user to the current `HttpServletRequest`.
+For example, the following will run as a user (which does not need to exist) with the username "user", the password "password", and the role "ROLE_USER":
+
+[NOTE]
+====
+The support works by associating the user to the `HttpServletRequest`.
+To associate the request to the `SecurityContextHolder` you need to ensure that the `SecurityContextPersistenceFilter` is associated with the `MockMvc` instance.
+A few ways to do this are:
+
+* Invoking <<test-mockmvc-setup,apply(springSecurity())>>
+* Adding Spring Security's `FilterChainProxy` to `MockMvc`
+* Manually adding `SecurityContextPersistenceFilter` to the `MockMvc` instance may make sense when using `MockMvcBuilders.standaloneSetup`
+====
+
+[source,java]
+----
+mvc
+	.perform(get("/").with(user("user")))
+----
+
+You can easily make customizations.
+For example, the following will run as a user (which does not need to exist) with the username "admin", the password "pass", and the roles "ROLE_USER" and "ROLE_ADMIN".
+
+[source,java]
+----
+mvc
+	.perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
+----
+
+If you have a custom `UserDetails` that you would like to use, you can easily specify that as well.
+For example, the following will use the specified `UserDetails` (which does not need to exist) to run with a `UsernamePasswordAuthenticationToken` that has a principal of the specified `UserDetails`:
+
+[source,java]
+----
+mvc
+	.perform(get("/").with(user(userDetails)))
+----
+
+You can run as anonymous user using the following:
+
+[source,java]
+----
+mvc
+	.perform(get("/").with(anonymous()))
+----
+
+This is especially useful if you are running with a default user and wish to execute a few requests as an anonymous user.
+
+If you want a custom `Authentication` (which does not need to exist) you can do so using the following:
+
+[source,java]
+----
+mvc
+	.perform(get("/").with(authentication(authentication)))
+----
+
+You can even customize the `SecurityContext` using the following:
+
+[source,java]
+----
+mvc
+	.perform(get("/").with(securityContext(securityContext)))
+----
+
+We can also ensure to run as a specific user for every request by using ``MockMvcBuilders``'s default request.
+For example, the following will run as a user (which does not need to exist) with the username "admin", the password "password", and the role "ROLE_ADMIN":
+
+[source,java]
+----
+mvc = MockMvcBuilders
+		.webAppContextSetup(context)
+		.defaultRequest(get("/").with(user("user").roles("ADMIN")))
+		.apply(springSecurity())
+		.build();
+----
+
+If you find you are using the same user in many of your tests, it is recommended to move the user to a method.
+For example, you can specify the following in your own class named `CustomSecurityMockMvcRequestPostProcessors`:
+
+[source,java]
+----
+public static RequestPostProcessor rob() {
+	return user("rob").roles("ADMIN");
+}
+----
+
+Now you can perform a static import on `SecurityMockMvcRequestPostProcessors` and use that within your tests:
+
+[source,java]
+----
+import static sample.CustomSecurityMockMvcRequestPostProcessors.*;
+
+...
+
+mvc
+	.perform(get("/").with(rob()))
+----
+
+===== Running as a User in Spring MVC Test with Annotations
+
+As an alternative to using a `RequestPostProcessor` to create your user, you can use annotations described in <<Testing Method Security>>.
+For example, the following will run the test with the user with username "user", password "password", and role "ROLE_USER":
+
+[source,java]
+----
+@Test
+@WithMockUser
+public void requestProtectedUrlWithUser() throws Exception {
+mvc
+		.perform(get("/"))
+		...
+}
+----
+
+Alternatively, the following will run the test with the user with username "user", password "password", and role "ROLE_ADMIN":
+
+[source,java]
+----
+@Test
+@WithMockUser(roles="ADMIN")
+public void requestProtectedUrlWithUser() throws Exception {
+mvc
+		.perform(get("/"))
+		...
+}
+----
+
+==== Testing HTTP Basic Authentication
+
+While it has always been possible to authenticate with HTTP Basic, it was a bit tedious to remember the header name, format, and encode the values.
+Now this can be done using Spring Security's `httpBasic` `RequestPostProcessor`.
+For example, the snippet below:
+
+[source,java]
+----
+mvc
+	.perform(get("/").with(httpBasic("user","password")))
+----
+
+will attempt to use HTTP Basic to authenticate a user with the username "user" and the password "password" by ensuring the following header is populated on the HTTP Request:
+
+[source,text]
+----
+Authorization: Basic dXNlcjpwYXNzd29yZA==
+----
+
+=== SecurityMockMvcRequestBuilders
+
+Spring MVC Test also provides a `RequestBuilder` interface that can be used to create the `MockHttpServletRequest` used in your test.
+Spring Security provides a few `RequestBuilder` implementations that can be used to make testing easier.
+In order to use Spring Security's `RequestBuilder` implementations ensure the following static import is used:
+
+[source,java]
+----
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
+----
+
+==== Testing Form Based Authentication
+
+You can easily create a request to test a form based authentication using Spring Security's testing support.
+For example, the following will submit a POST to "/login" with the username "user", the password "password", and a valid CSRF token:
+
+[source,java]
+----
+mvc
+	.perform(formLogin())
+----
+
+It is easy to customize the request.
+For example, the following will submit a POST to "/auth" with the username "admin", the password "pass", and a valid CSRF token:
+
+[source,java]
+----
+mvc
+	.perform(formLogin("/auth").user("admin").password("pass"))
+----
+
+We can also customize the parameters names that the username and password are included on.
+For example, this is the above request modified to include the username on the HTTP parameter "u" and the password on the HTTP parameter "p".
+
+[source,java]
+----
+mvc
+	.perform(formLogin("/auth").user("u","admin").password("p","pass"))
+----
+
+[[test-logout]]
+==== Testing Logout
+
+While fairly trivial using standard Spring MVC Test, you can use Spring Security's testing support to make testing log out easier.
+For example, the following will submit a POST to "/logout" with a valid CSRF token:
+
+[source,java]
+----
+mvc
+	.perform(logout())
+----
+
+You can also customize the URL to post to.
+For example, the snippet below will submit a POST to "/signout" with a valid CSRF token:
+
+[source,java]
+----
+mvc
+	.perform(logout("/signout"))
+----
+
+=== SecurityMockMvcResultMatchers
+
+At times it is desirable to make various security related assertions about a request.
+To accommodate this need, Spring Security Test support implements Spring MVC Test's `ResultMatcher` interface.
+In order to use Spring Security's `ResultMatcher` implementations ensure the following static import is used:
+
+[source,java]
+----
+import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*;
+----
+
+==== Unauthenticated Assertion
+
+At times it may be valuable to assert that there is no authenticated user associated with the result of a `MockMvc` invocation.
+For example, you might want to test submitting an invalid username and password and verify that no user is authenticated.
+You can easily do this with Spring Security's testing support using something like the following:
+
+[source,java]
+----
+mvc
+	.perform(formLogin().password("invalid"))
+	.andExpect(unauthenticated());
+----
+
+==== Authenticated Assertion
+
+It is often times that we must assert that an authenticated user exists.
+For example, we may want to verify that we authenticated successfully.
+We could verify that a form based login was successful with the following snippet of code:
+
+[source,java]
+----
+mvc
+	.perform(formLogin())
+	.andExpect(authenticated());
+----
+
+If we wanted to assert the roles of the user, we could refine our previous code as shown below:
+
+[source,java]
+----
+mvc
+	.perform(formLogin().user("admin"))
+	.andExpect(authenticated().withRoles("USER","ADMIN"));
+----
+
+Alternatively, we could verify the username:
+
+[source,java]
+----
+mvc
+	.perform(formLogin().user("admin"))
+	.andExpect(authenticated().withUsername("admin"));
+----
+
+We can also combine the assertions:
+
+[source,java]
+----
+mvc
+	.perform(formLogin().user("admin").roles("USER","ADMIN"))
+	.andExpect(authenticated().withUsername("admin"));
+----
+
+We can also make arbitrary assertions on the authentication
+
+[source,java]
+----
+mvc
+	.perform(formLogin())
+	.andExpect(authenticated().withAuthentication(auth ->
+		assertThat(auth).isInstanceOf(UsernamePasswordAuthenticationToken.class)));
+----

+ 150 - 0
docs/manual/src/docs/asciidoc/_includes/test/webtestclient.adoc

@@ -0,0 +1,150 @@
+[[test-webflux]]
+== WebFlux Support
+
+[[test-erms]]
+=== Reactive Method Security
+
+For example, we can test our example from <<jc-erms>> using the same setup and annotations we did in <<test-method>>.
+Here is a minimal sample of what we can do:
+
+[source,java]
+----
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = HelloWebfluxMethodApplication.class)
+public class HelloWorldMessageServiceTests {
+	@Autowired
+	HelloWorldMessageService messages;
+
+	@Test
+	public void messagesWhenNotAuthenticatedThenDenied() {
+		StepVerifier.create(this.messages.findMessage())
+			.expectError(AccessDeniedException.class)
+			.verify();
+	}
+
+	@Test
+	@WithMockUser
+	public void messagesWhenUserThenDenied() {
+		StepVerifier.create(this.messages.findMessage())
+			.expectError(AccessDeniedException.class)
+			.verify();
+	}
+
+	@Test
+	@WithMockUser(roles = "ADMIN")
+	public void messagesWhenAdminThenOk() {
+		StepVerifier.create(this.messages.findMessage())
+			.expectNext("Hello World!")
+			.verifyComplete();
+	}
+}
+----
+
+[[test-webtestclient]]
+=== WebTestClientSupport
+
+Spring Security provides integration with `WebTestClient`.
+The basic setup looks like this:
+
+[source,java]
+----
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = HelloWebfluxMethodApplication.class)
+public class HelloWebfluxMethodApplicationTests {
+	@Autowired
+	ApplicationContext context;
+
+	WebTestClient rest;
+
+	@Before
+	public void setup() {
+		this.rest = WebTestClient
+			.bindToApplicationContext(this.context)
+			// add Spring Security test Support
+			.apply(springSecurity())
+			.configureClient()
+			.filter(basicAuthentication())
+			.build();
+	}
+	// ...
+}
+----
+
+==== Authentication
+
+After applying the Spring Security support to `WebTestClient` we can use either annotations or `mutateWith` support.
+For example:
+
+[source,java]
+----
+@Test
+public void messageWhenNotAuthenticated() throws Exception {
+	this.rest
+		.get()
+		.uri("/message")
+		.exchange()
+		.expectStatus().isUnauthorized();
+}
+
+// --- WithMockUser ---
+
+@Test
+@WithMockUser
+public void messageWhenWithMockUserThenForbidden() throws Exception {
+	this.rest
+		.get()
+		.uri("/message")
+		.exchange()
+		.expectStatus().isEqualTo(HttpStatus.FORBIDDEN);
+}
+
+@Test
+@WithMockUser(roles = "ADMIN")
+public void messageWhenWithMockAdminThenOk() throws Exception {
+	this.rest
+		.get()
+		.uri("/message")
+		.exchange()
+		.expectStatus().isOk()
+		.expectBody(String.class).isEqualTo("Hello World!");
+}
+
+// --- mutateWith mockUser ---
+
+@Test
+public void messageWhenMutateWithMockUserThenForbidden() throws Exception {
+	this.rest
+		.mutateWith(mockUser())
+		.get()
+		.uri("/message")
+		.exchange()
+		.expectStatus().isEqualTo(HttpStatus.FORBIDDEN);
+}
+
+@Test
+public void messageWhenMutateWithMockAdminThenOk() throws Exception {
+	this.rest
+		.mutateWith(mockUser().roles("ADMIN"))
+		.get()
+		.uri("/message")
+		.exchange()
+		.expectStatus().isOk()
+		.expectBody(String.class).isEqualTo("Hello World!");
+}
+----
+
+
+==== CSRF Support
+
+Spring Security also provides support for CSRF testing with `WebTestClient`.
+For example:
+
+[source,java]
+----
+this.rest
+	// provide a valid CSRF token
+	.mutateWith(csrf())
+	.post()
+	.uri("/login")
+	...
+----

+ 1 - 1
docs/manual/src/docs/asciidoc/index.adoc

@@ -10,7 +10,7 @@ include::{include-dir}/preface/index.adoc[]
 
 include::{include-dir}/architecture/index.adoc[]
 
-include::{include-dir}/test.adoc[]
+include::{include-dir}/test/index.adoc[]
 
 include::{include-dir}/web.adoc[]