Spring Security测试异常:@WithMockUser未生效,无权限测试意外通过
问题根源
你当前使用的MockitoJUnitRunner.class仅负责处理Mockito相关注解(如@InjectMocks),不会触发Spring Security的方法安全切面。这导致@PreAuthorize注解完全没有生效,无论你模拟什么角色,目标方法都会直接执行,不会进行权限校验。
解决方案
要让@PreAuthorize在测试中生效,需要切换到Spring测试上下文,启用方法级安全的切面支持,具体步骤如下:
1. 替换测试Runner并启用方法安全
将测试类的@RunWith(MockitoJUnitRunner.class)替换为Spring的测试Runner,并添加注解启用方法级安全:
- Spring Security 6+ 用
@EnableMethodSecurity - 旧版本用
@EnableGlobalMethodSecurity(prePostEnabled = true)
2. 调整测试类配置
如果是Spring Boot项目,推荐用@SpringBootTest加载最小化上下文;如果是普通Spring项目,用@ContextConfiguration指定需要加载的配置类和Service类。
修改后的测试类示例(Spring Boot场景):
@RunWith(SpringRunner.class) @SpringBootTest(classes = {DownloadPhasesFilesService.class}) @EnableMethodSecurity // 启用方法级安全校验 public class DownloadPhasesFilesServiceTest { @Autowired private DownloadPhasesFilesService downloadPhasesFilesService; @Test @WithMockUser(authorities = {"ROLE_READ" }) public void getPhase2FilePathRoleWise_shouldDenyAccessForReadRole() { // Given: final BatchJob batchJob = BatchJob.builder() .id(1L) .telSecJobId("123") .status(PHASE_TWO_COMPLETED) .phase2FilePath("phase2") .baseMac(new MacAddress("aa:bb:cc:dd:ee:ff").getPlainMacAddress()) .tenant(Natco.builder().natcoCode("pl").build()) .model(Model.builder().modelName("modelName").oemName("oemName").build()) .build(); // 预期抛出权限拒绝异常 Assertions.assertThrows(AccessDeniedException.class, () -> { downloadPhasesFilesService.getPhase2FilePathRoleWise(batchJob); }); } }
3. 调整测试断言逻辑
原测试断言返回值的逻辑不符合预期,现在需要改为断言抛出AccessDeniedException,以此验证权限校验生效。
补充说明
@WithMockUser的参数可以用roles简化写法:@WithMockUser(roles = "READ")会自动为角色添加ROLE_前缀,等同于authorities = {"ROLE_READ"}- 确保Spring Security与Spring版本兼容(如Spring Security 6需搭配Spring 6+)
内容的提问来源于stack exchange,提问作者EV Experience
相关产品推荐
相关产品推荐

