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

Spring Boot @WebMvcTest使用@WithUserDetails出现空指针问题求助

问题分析与解决方案

这个空指针问题的核心原因是**@WithUserDetails的执行时机早于你在测试方法中设置的Mock返回值**。

当Spring Security的WithSecurityContextTestExecutionListener在测试方法执行前(也就是beforeTestMethod阶段)创建SecurityContext时,会调用你Mock的userDetailsService.loadUserByUsername,但此时你在testSaveBackground方法里写的given(userDetailsService.loadUserByUsername(...)).willReturn(...)还没有执行,所以loadUserByUsername返回null,进而触发空指针异常。


解决步骤

1. 将Mock Stubbing移至@Before方法

把初始化userDetailsService返回值的代码移到测试类的@Before方法中,确保在@WithUserDetails执行前就完成Stubbing:

@RunWith(SpringRunner.class)
@WebMvcTest(PDPController.class)
@AutoConfigureMockMvc(addFilters = false)
public class PDPControllerTests {
    @Autowired
    private MockMvc mvc;
    @Autowired
    private ObjectMapper objectMapper;
    @MockBean
    private PDPService pdpService;
    @MockBean(name = "userDetailsService")
    private MyUserDetailsService userDetailsService;
    
    private Account account;
    private Employee employee;

    @Before
    public void setUp() {
        account = new Account();
        employee = new Employee();
        // 提前设置userDetailsService的返回值,确保@WithUserDetails调用时能拿到对象
        given(userDetailsService.loadUserByUsername(anyString())).willReturn(new EmployeeDetails(employee, account));
    }

    @Test
    @WithUserDetails(value = "someemail@email.com", userDetailsServiceBeanName = "userDetailsService")
    public void testSaveBackground_returns_result_from_service() throws Exception {
        PersonalDevelopmentPlan pdp = new PersonalDevelopmentPlan();
        pdp.setEmployee(EMPLOYEE_ID);
        
        given(pdpService.saveBackground(eq(EMPLOYEE_ID), any(), anyInt())).willReturn(pdp);
        
        mvc.perform(patch(URL_WITH_ID + "/background").secure(true)
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(pdp)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.employee", Matchers.is(EMPLOYEE_ID)));
    }
}

2. 额外检查项

  • 确认你的EmployeeDetails构造方法不会因为传入的employee或account为空而触发内部空指针(比如如果构造方法里直接访问employee.getId()但employee未初始化的话)。可以给employee和account设置必要的属性,比如:
    employee.setId(EMPLOYEE_ID);
    account.setEmail("someemail@email.com");
    
  • 确保@MockBean(name = "userDetailsService")的名称和@WithUserDetails中指定的userDetailsServiceBeanName完全一致,避免Spring找不到对应的Bean。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:17:48