Careeroza
WithMockUser and Related Annotations
The Annotations
| Annotation | Puts into the SecurityContext | Use for |
|---|---|---|
@WithMockUser | a fake user (default "user", role USER) | most URL and method rule tests |
@WithMockUser(username="meera", roles="ADMIN") | user meera with ROLE_ADMIN | role checks |
@WithMockUser(authorities="SCOPE_orders.read") | exact authorities (no ROLE_ prefix added) | authority/scope checks |
@WithAnonymousUser | an anonymous token | override a class-level user for one test |
@WithUserDetails("[email protected]") | the user loaded from your UserDetailsService | when code needs your custom UserDetails |
custom @WithSecurityContext | anything you build | your own principal type, e.g. a ShopEaseUser |
Using Them
@WebMvcTest(AdminProductController.class)
@Import(SecurityConfig.class)
class AdminProductControllerTest {
@Autowired MockMvc mvc;
@MockitoBean ProductService productService;
@Test
@WithMockUser(username = "asha", roles = "CUSTOMER")
void customerIsForbidden() throws Exception {
mvc.perform(delete("/api/admin/products/7").with(csrf()))
.andExpect(status().isForbidden());
verifyNoInteractions(productService);
}
@Test
@WithMockUser(username = "meera", roles = "ADMIN")
void adminCanDelete() throws Exception {
mvc.perform(delete("/api/admin/products/7").with(csrf()))
.andExpect(status().isNoContent());
verify(productService).delete(7L);
}
}Testing Method Security
@SpringBootTest
class OrderServiceSecurityTest {
@Autowired OrderService orderService;
@MockitoBean OrderRepository orderRepository;
@Test
@WithMockUser(authorities = "SCOPE_orders.read")
void readScopeCanListOrders() {
when(orderRepository.findByCustomerIdOrderByPlacedAtDesc("asha")).thenReturn(List.of());
assertThat(orderService.findByCustomer("asha")).isEmpty();
}
@Test
@WithMockUser(authorities = "SCOPE_profile")
void withoutScopeAccessIsDenied() {
assertThatThrownBy(() -> orderService.findByCustomer("asha"))
.isInstanceOf(AccessDeniedException.class);
}
}Note: @PreAuthorize only works through the Spring proxy, so get the service from the context (@Autowired), never with new OrderService(...).