Test Setup

Why Test Security

Security rules are code, and they break silently: one wrong requestMatchers order and /api/admin/** becomes public. A test per rule ("anonymous gets 401, customer gets 403, admin gets 200") catches this in CI before it reaches production.

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

A Slice Test with Your Real Rules

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(ProductController.class)
@Import(SecurityConfig.class)              // load YOUR filter chain, not a default one
class ProductControllerSecurityTest {

    @Autowired MockMvc mvc;
    @MockitoBean ProductService productService;   // Spring Boot 3.4+ (older: @MockBean)

    @Test
    void anyoneCanBrowseProducts() throws Exception {
        mvc.perform(get("/api/products")).andExpect(status().isOk());
    }

    @Test
    void anonymousCannotCreateProducts() throws Exception {
        mvc.perform(post("/api/products").contentType(MediaType.APPLICATION_JSON).content("{}"))
           .andExpect(status().isUnauthorized());
    }
}

Tip: @WebMvcTest loads only the web layer, so tests run in about a second. Always @Import your security configuration — otherwise you are testing Spring Boot's defaults, not your rules.