You need to enable JavaScript to run this app. SpringBoot中@PreAuthorize接口JUnit测试表达式评估报错求助
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot中@PreAuthorize接口JUnit测试表达式评估报错求助

问题根因

  • 测试类中使用@Mock注解生成的SecurityService实例仅为Mockito普通Mock对象,未注册到Spring测试上下文中,导致@PreAuthorize的SpEL表达式无法找到名为securityService的Bean,触发表达式解析失败。
  • Mock规则与实际请求参数不匹配:你定义的when(securityService.isValidUser("test.test@gmail.com"))匹配的入参是邮箱字符串,但实际测试请求中传递的id参数是789988,即使Bean能找到也会返回null触发权限校验不通过。
  • @WebMvcTest默认不会自动启用方法安全校验相关配置,需要额外开启注解支持。

解决方案

步骤1:替换@Mock为@MockBean

@MockBean是Spring Boot提供的测试注解,会将Mock后的实例注册到Spring上下文中,SpEL表达式可正常识别到@securityService这个Bean。

步骤2:修正Mock规则匹配实际请求参数

和你测试请求中传入的id值保持一致,或者使用Mockito的通配符匹配任意入参。

步骤3:在测试类上添加方法安全注解

如果你的项目用的是Spring Security 6+,添加@EnableMethodSecurity注解到测试类开启PreAuthorize注解支持;如果是旧版本用@EnableGlobalMethodSecurity(prePostEnabled = true)。

步骤4:补充Context配置

在@ContextConfiguration中指定你需要加载的控制器类、安全配置类,避免测试上下文缺失必要Bean。

修正后的测试代码

@WebMvcTest
@EnableMethodSecurity // Spring Security 6+ 版本使用,旧版本替换为@EnableGlobalMethodSecurity(prePostEnabled = true)
@ContextConfiguration(classes = {AccountController.class, SecurityConfig.class}) // 替换为你实际的控制器类、安全配置类全路径
class WebLayerTest {

    @Autowired
    private MockMvc mockMvc;

    // 替换@Mock为@MockBean
    @MockBean
    SecurityService securityService;

    @Test
    void accountTest() throws Exception {
        // 修正入参匹配请求中的id值789988,也可用anyString()匹配任意字符串
        when(securityService.isValidUser("789988")).thenReturn(true);

        this.mockMvc.perform(MockMvcRequestBuilders.get("/account?id=789988&sec=test@123")
                .contentType(MediaType.APPLICATION_JSON)
                .header("Origin", "*"))
                .andDo(print())
                .andExpect(status().isOk());
    }
}

补充说明

如果修正后仍然提示参数解析失败,可将@PreAuthorize的表达式修改为@securityService.isValidUser(#request.getParameter('id')),直接从请求对象中获取参数,避免参数名解析异常。

内容的提问来源于stack exchange,提问作者Initials

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 23:27:10