Disable Spring Security config class for @WebMvcTest in Spring Boot

35,566

Solution 1

You can set secure=false in the @WebMvcTest annoation. It will skip the spring security MockMvc auto configuration in your Test

@WebMvcTest(controllers = SomeController.class, secure = false)
public class SomeControllerTest {

Note by the author: As of 2021, this answer has been obsolete for a few years and it probably won't work for you.

Solution 2

For me in Spring Boot 2.2.4 (JUnit5) the below seems to have worked and bypass the security filter.

@ExtendWith(SpringExtension.class)
@WebMvcTest(SomeController.class)
@AutoConfigureMockMvc(addFilters = false)
public class SomeControllerTest {
...

Note: this simply disables any filters in the SpringSecurity configuration. It won't disable the security completely. In other words it will still bootstrap security without loading any filters.

Solution 3

In Spring Boot 2.2.6, @WebMvcTest is meta annotated with @AutoConfigureWebMvc which auto-configure org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration as you can see in spring.factories of spring-boot-test-autoconfigure.jar

So you just have to exclude SecurityAutoConfiguration in your test to disable Spring Security :

@WebMvcTest(excludeAutoConfiguration = SecurityAutoConfiguration.class) 

Solution 4

With Spring Security 4+, I find @WithMockUser annotation to be very handy. It provides a mock user and password to test spring security methods annotated with @PreAuthorize or @PostAuthorize. All you need to do is annotate the test method with @WithMockUser. The default role for the user is USER. You can override the default username and role too.

//default
@Test
@WithMockUser
public void getProfile() {
   //your test here
} 

//with username and roles
@Test
@WithMockUser(username = "john", roles={"ADMIN"})
public void getProfile() {
   //your test here
} 

NOTE: This annotation can be used for classes.

@WithMockUser(username = "john", roles={"ADMIN"})
public class UsersAdminSecurityTest {
} 

Solution 5

In Spring Boot 2.4 both secure flags were removed and none of the answers here actually work.

I ended up excluding all the security myself and wrapping it around in a custom annotation.

import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@WebMvcTest(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebSecurityConfigurer.class)},
            excludeAutoConfiguration = {SecurityAutoConfiguration.class,
                                        SecurityFilterAutoConfiguration.class,
                                        OAuth2ClientAutoConfiguration.class,
                                        OAuth2ResourceServerAutoConfiguration.class})
public @interface UnsecuredWebMvcTest {
    @AliasFor(annotation = WebMvcTest.class, attribute = "controllers")
    Class<?>[] value() default {};

    @AliasFor(annotation = WebMvcTest.class, attribute = "controllers")
    Class<?>[] controllers() default {};
}
Share:
35,566
Johan
Author by

Johan

Updated on October 12, 2021

Comments

  • Johan
    Johan over 2 years

    Recently I have added Spring Security to my Spring Boot project using the following class:

    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class MySecurityConfig {
    }
    

    as result, by default all my URLs are now protected with authentication and a self-generated password.

    The problem is that all tests in a @WebMvcTest class that I used for unit-testing a controller:

    @RunWith(SpringRunner.class)
    @WebMvcTest(SomeController.class)
    public class SomeControllerTest {...}
    

    are now failing everywhere because of lack of authorization.

    Question: can I tell @Test methods to ignore authorization so they keep succeeding as before?

    How can I prevent the @EnableWebSecurity config class from being picked on a specific @WebMvcTest unit testing class?

    I would like the tests already in place to be able to still go through and to test the authentication features separately later on.

    So far I have tried to use a nested config class in the testing class in order to exclude security configs:

    @RunWith(SpringRunner.class)
    @WebMvcTest(SomeController.class)
    public class SomeControllerTest {
    
        @Configuration
        @EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class})
        static class ContextConfiguration { }
    
     ....}
    

    but it seems not to work.

    NOTE : I am using Spring Boot 1.5.8