You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot测试@WithMockUser时@AuthenticationPrincipal注入为null

Controller层MockMvc测试@AuthenticationPrincipal入参为null问题

问题现象

项目升级至Java 17、Spring Boot 2.5.5、Spring Cloud 2020.0.5版本后,Controller层单元测试出现异常:

  • Controller方法中标记@AuthenticationPrincipal注解的Authentication类型入参值为null
  • 方法内部直接调用SecurityContextHolder.getContext().getAuthentication()可正常获取@WithMockUser生成的模拟认证对象

相关代码片段

测试基类配置

@SpringBootTest
@WithMockUser(username = "test_user",authorities = "Configured_allacess_authority")
public abstract class BaseControllerTest extends DatabaseIT {

    protected static long counter;
    protected MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;
    @Autowired
    protected ObjectMapper objectMapper;
    protected MockRestServiceServer restServiceServer;
    @Autowired
    RestTemplate restTemplate;

    @BeforeEach
    protected void setup() {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                .build();
        restServiceServer = MockRestServiceServer.createServer(restTemplate);
    }
}

测试执行逻辑

mockMvc.perform(request)
       .andExpect(status().isOk())
       .andExpect(content().contentType(MediaType.APPLICATION_JSON))
       .andExpect(content().json(s));

异常Controller方法

public ResponseEntity<?> getSomething (
    @Parameter(description = "ID") final String id,
    @ApiIgnore @AuthenticationPrincipal Authentication user){
    // 业务逻辑
}

根因

手动通过WebApplicationContext构建MockMvc实例时,未显式应用Spring Security测试模块的配置,导致@AuthenticationPrincipal对应的参数解析器AuthenticationPrincipalArgumentResolver未被注册到MockMvc的参数解析链路中:

  • 直接读取SecurityContextHolder是直接获取线程上下文绑定的安全上下文值,不经过MVC参数解析流程,因此可以正常拿到模拟用户信息
  • 注解标记的Controller入参需要经过MVC参数解析器链完成注入,缺少对应解析器时就会出现注入值为null的情况
  • 升级到指定版本后,Spring Security测试模块不再默认给手动构建的MockMvc实例隐式注册安全相关组件,必须显式声明配置。

修复方法

  1. 确认测试模块已引入spring-security-test依赖
  2. 修改测试基类的MockMvc构建逻辑,显式应用Spring Security测试配置:
// 导入静态配置类
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;

@BeforeEach
protected void setup() {
    mockMvc = MockMvcBuilders
            .webAppContextSetup(webApplicationContext)
            // 新增该行,加载Spring Security测试过滤器、参数解析器等组件
            .apply(springSecurity())
            .build();
    restServiceServer = MockRestServiceServer.createServer(restTemplate);
}

修改后重新执行测试,@AuthenticationPrincipal标记的入参即可正常注入模拟认证对象。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:54:24