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

JUnit泛型抽象测试基类执行测试时serviceBean空指针未初始化问题

问题根因
  • @Before方法重写未触发父类初始化逻辑:JUnit 4中子类重写父类带有@Before注解的方法时,不会自动执行父类的方法逻辑。你当前子类定义了同名的setup()方法且加了@Before注解,但没有主动调用super.setup(),父类中初始化serviceBean、EntityManager的逻辑完全没有执行,自然会出现空指针异常,不仅serviceBean为null,@After中访问的realEntityManager也未初始化。
  • 父类初始化顺序存在逻辑漏洞:父类setup()方法中先调用getPUName()创建EntityManagerFactory,之后才执行setServiceBean()初始化服务实例。而子类的getPUName()实现直接依赖未初始化的serviceBean,就算加了super.setup(),第一次执行时也会先触发空指针。
修复方案
  1. 子类setup()方法第一行添加父类逻辑调用:
@Before
public void setup() {
    super.setup(); // 新增该行,优先执行父类初始化
    inputQuery = new Query<>();
    // 剩余原有打桩逻辑不变
}
  1. 调整父类初始化顺序,优先初始化服务实例再获取PU名称,避免空依赖:
@Before
public void setup() {
    // 优先初始化服务Bean
    setServiceBean();
    if (factory == null) {
        factory = Persistence.createEntityManagerFactory(getPUName());
    }
    realEntityManager = factory.createEntityManager();
    EntityManager spy = spy(realEntityManager);
    try {
        Field entityManagerField = serviceBean.getClass().getDeclaredField("entityManager");
        entityManagerField.setAccessible(true);
        entityManagerField.set(serviceBean, spy);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        throw new AssertionError("代码运行不应该到达此处");
    }
}
  1. (可选优化)修改子类getPUName()实现,不依赖实例化的serviceBean,从根源避免空指针风险:
@Override
public String getPUName() {
    // 直接使用类字面量获取名称,不依赖实例对象
    return SubscriptionHistoryPersistenceServiceBean.class.getName();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 18:24:04