Skip to content

Testing Support

The Spring Security as other Spring modules provides support for integration testing of your application. There are various security testing aspects supported. Spring Security provides integration with well known MockMvc component used for web application and REst API testing. You can also utilize test annotations related with mMethod security.

Method Security

Spring Security provides following convenient annotations, which you can use in your integration tests.

  • @WithMockUser - test will be run as a user with the username user, the password password, and the roles ROLE_USER. SecurityContext is populated by UsernamePasswordAuthenticationToken.
  • @WithAnonymousUser - test will be run with anonymous user.
  • @WithUserDetails - test will be run with user retrieved from configured UserDetailService Bean.
  • @WithSecurityContext - the most flexible choice, which allows to define custom SecurityContext.

Examples of usage:

    @DisplayName("call hello authentication")
    @WithMockUser(username = "admin", password = "admin")
    @Test
    void helloAuthentication() throws Exception {
        assertEquals("Hello...", helloService.sayHello());
    }

You can create mock user utilizing meta annotation @WithMockUser, ane then reuse it for any test.

    @Retention(RetentionPolicy.RUNTIME)
    @WithMockUser(username="operator", password="password", roles="ROLE_OPERATOR")
    public @interface WithMockOperator {
}
    @DisplayName("call protected books endpoint as operator user")
    @WithMockOperator
    @Test
    void allBooksWithOperator() throws Exception {
        this.mvc.perform(get("/library/books"))
                .andExpect(status().is4xxClientError()).andReturn();
    }

MockMvc setup

Sprint Security integrates with MockMvc, but you need to configure _MockMvc_instance in test class as following:

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mvc;

    @BeforeEach
    public void setup() {
        mvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                .apply(springSecurity())
                .build();
    }

RequestPostProcessors

When you setup MockMvc with security, you can execute HTTP Request with Request post processor, which can execute request as specific User, and authentication method.

Executing request with USer and HTTP Basic authentication:

    @DisplayName("call protected books endpoint without authentication")
    @Test
    void allBooksAuthentication() throws Exception {
        this.mvc.perform(get("/library/books").with(httpBasic("admin","admin")))
                .andExpect(status().is2xxSuccessful()).andReturn();
    }

You can also use specific SecurityContext:

    @DisplayName("call protected books endpoint without authentication")
    @Test
    void allBooksAuthentication() throws Exception {
        this.mvc.perform(get("/library/books").with(securityContext(secContext)))
                .andExpect(status().is2xxSuccessful()).andReturn();
    }

You can even define reusable User as method:

    public static RequestPostProcessor rob() {
        return user("admin").roles("ROLE_ADMIN");
    }

    @DisplayName("call protected books endpoint without authentication")
    @Test
    void allBooksAuthentication() throws Exception {
        this.mvc.perform(get("/library/books").with(adminUser()))
                .andExpect(status().is2xxSuccessful()).andReturn();
    }

CSRF

Call request with CSRF token:

    @DisplayName("call hello with csrf token")
    @Test
    void helloWithArgumentCsrf() throws Exception {
        this.mvc.perform(post("/hello").queryParam("name","Peter")
                        .with(csrf())
                        .with(adminUser()))
                .andExpect(status().is2xxSuccessful()).andReturn();
    }

Or invalid CSRF token:

    @DisplayName("call hello with invalid csrf token")
    @Test
    void helloWithArgumentInvalidCsrf() throws Exception {
        this.mvc.perform(post("/hello").queryParam("name","Peter")
                        .with(csrf().useInvalidToken())
                        .with(adminUser()))
                .andExpect(status().is4xxClientError()).andReturn();
    }