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

使用Mockito测试时出现ExceptionInInitializerError,如何忽略类的静态字段初始化?

你遇到的ExceptionInInitializerError是因为JVM首次加载StringTools类时,会先初始化所有静态字段,此时会调用Activator.getNumberOfDays(),而单测环境下没有Activator的运行环境,所以初始化失败抛出错误。普通Mockito mock静态类时默认会触发类加载,所以无法绕过这个逻辑,以下是可行的实现方案:


方案1:使用PowerMock直接抑制静态初始化

PowerMock原生支持跳过指定类的静态初始化逻辑,是最直接的适配方案:

  1. 单测类添加如下注解:
@RunWith(PowerMockRunner.class)
// 填写StringTools的全限定类名
@SuppressStaticInitializationFor("com.xxx.xxx.StringTools")
public class UtilsTest {
}
  1. 正常mock getCurrentName()静态方法即可,不会触发_numberOfDays的初始化逻辑。

方案2:使用高版本Mockito(3.4+)的静态Mock参数绕过

Mockito 3.4及以上版本提供了是否触发静态初始化的配置项,无需引入PowerMock:

@Test
public void testConcatString() {
    // 配置mock时不触发静态初始化
    try (MockedStatic<StringTools> mockedStatic = Mockito.mockStatic(
        StringTools.class, 
        Mockito.withSettings().invokeStaticInitializers(false)
    )) {
        // 配置getCurrentName的mock返回值
        mockedStatic.when(StringTools::getCurrentName).thenReturn("mockName");
        // 执行测试
        String result = Utils.concatString("test");
        // 校验结果
        Assert.assertEquals("testmockName", result);
    }
}

方案3:业务代码优化(推荐)

从代码设计层面调整,避免无关逻辑耦合,后续所有场景都不会出现类似问题:
将需要依赖运行环境的静态字段改为懒加载,只有被使用时才触发初始化:

public class StringTools{
    // 静态内部类只有被访问时才会加载初始化
    private static class DaysHolder {
        private static final int _numberOfDays = Activator.getNumberOfDays();
    }
    
    public static String getCurrentName(){
        // 只要该方法没有用到DaysHolder._numberOfDays,就不会触发初始化
        ...
    }

    // 只有用到_numberOfDays的方法才会触发初始化
    public static int getDays() {
        return DaysHolder._numberOfDays;
    }
}

调整后无需任何测试框架hack,直接mock静态方法即可正常运行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:54:08