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

Wicket 9单元测试用Mockito模拟HttpSession时getLoginName空指针问题

问题根因
  • 你创建的mock SecureWebSession 实例未绑定到WicketTester运行上下文,Wicket处理请求时仍自动创建原生SecureWebSession实例,mock对象完全未生效
  • 原生SecureWebSession构造方法调用getSession(false)时,测试环境下此时还没有已创建的HttpSession,因此返回null,后续调用getLoginName触发空指针
推荐解决方案(最轻量,符合单元测试逻辑)

直接mock getLoginName 方法绕开内部实现,不需要处理HttpSession相关逻辑:

  1. 给你已创建的mock SecureWebSession 增加方法stub配置,指定getLoginName返回测试值
  2. 将mock的SecureWebSession绑定到WicketTester上下文,替换Wicket自动生成的原生session
  3. 移除冗余的MockHttpServletRequest、MockHttpSession相关配置,完全不需要用到

修改后的setUp核心代码如下:

@BeforeEach
public void setUp() {
    // 原有SecurityContext配置保留
    Authentication authentication = Mockito.mock(Authentication.class);
    SecurityContext securityContext = Mockito.mock(SecurityContext.class);
    Mockito.when(securityContext.getAuthentication()).thenReturn(authentication);
    Mockito.when(authentication.isAuthenticated()).thenReturn(true);
    SecurityContextHolder.setContext(securityContext); 

    // 构造mock的SecureWebSession,配置所有需要的方法
    SecureWebSession secureWebSession = Mockito.mock(SecureWebSession.class);
    Roles roles = new Roles();
    roles.add("SUPER_ADMIN");
    Mockito.when(secureWebSession.getRoles()).thenReturn(roles); 
    // 新增这行,直接指定getLoginName返回测试值,完全绕开内部httpSession逻辑
    Mockito.when(secureWebSession.getLoginName()).thenReturn("test");

    tester = new WicketTester(webApplication);
    // 新增这行,把mock的session绑定到tester上下文
    tester.setSession(secureWebSession);
}
备选方案(需使用原生SecureWebSession实现时使用)

如果你的测试需要验证SecureWebSession本身的逻辑,不能mock整个类,可通过提前初始化HttpSession解决空指针:

  1. 测试时使用自定义的WebApplication子类,重写newSession方法,在创建Session前提前初始化HttpSession,保证getSession(false)能拿到实例
  2. 再往HttpSession中写入loginName属性即可
@BeforeEach
public void setUp() {
    // 原有SecurityContext配置保留
    Authentication authentication = Mockito.mock(Authentication.class);
    SecurityContext securityContext = Mockito.mock(SecurityContext.class);
    Mockito.when(securityContext.getAuthentication()).thenReturn(authentication);
    Mockito.when(authentication.isAuthenticated()).thenReturn(true);
    SecurityContextHolder.setContext(securityContext); 

    // 自定义测试用WebApplication,提前创建HttpSession
    WebApplication testApp = new MyWicketApplication() {
        @Override
        public Session newSession(Request request, Response response) {
            MockHttpServletRequest containerReq = (MockHttpServletRequest) request.getContainerRequest();
            // 提前创建session,让后续getSession(false)可返回非null值
            containerReq.getSession(true);
            containerReq.getSession().setAttribute("loginName", "test");
            return super.newSession(request, response);
        }
    };
    tester = new WicketTester(testApp);
}
注意事项
  • Wicket Session与请求周期强绑定,必须在调用startPage前完成session的绑定/配置,否则Wicket会自动创建原生Session覆盖你的配置
  • 单元测试场景优先选用第一种方案,只mock当前测试依赖的外部方法,不需要关心SecureWebSession的内部实现,测试逻辑更简洁可维护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:06:03