JUnit泛型抽象测试基类执行测试时serviceBean空指针未初始化问题
问题根因
- @Before方法重写未触发父类初始化逻辑:JUnit 4中子类重写父类带有
@Before注解的方法时,不会自动执行父类的方法逻辑。你当前子类定义了同名的setup()方法且加了@Before注解,但没有主动调用super.setup(),父类中初始化serviceBean、EntityManager的逻辑完全没有执行,自然会出现空指针异常,不仅serviceBean为null,@After中访问的realEntityManager也未初始化。 - 父类初始化顺序存在逻辑漏洞:父类
setup()方法中先调用getPUName()创建EntityManagerFactory,之后才执行setServiceBean()初始化服务实例。而子类的getPUName()实现直接依赖未初始化的serviceBean,就算加了super.setup(),第一次执行时也会先触发空指针。
修复方案
- 子类
setup()方法第一行添加父类逻辑调用:
@Before public void setup() { super.setup(); // 新增该行,优先执行父类初始化 inputQuery = new Query<>(); // 剩余原有打桩逻辑不变 }
- 调整父类初始化顺序,优先初始化服务实例再获取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("代码运行不应该到达此处"); } }
- (可选优化)修改子类
getPUName()实现,不依赖实例化的serviceBean,从根源避免空指针风险:
@Override public String getPUName() { // 直接使用类字面量获取名称,不依赖实例对象 return SubscriptionHistoryPersistenceServiceBean.class.getName(); }
内容的提问来源于stack exchange,提问作者WesternGun
相关产品推荐
相关产品推荐

