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

如何使用Mockito成功Mock含静态代码块的Abc类?

如何Mock带有静态初始化块且会抛出异常的类(JUnit 4 + Mockito 4.8.1)

问题场景

现有如下Abc类,其静态初始化块会调用可能抛出AbcException的静态方法fun():

class Abc{
    static void fun() throws AbcException{
        throw new Exception("Some exception message");
    }
    
    static{
        try{
            fun();
        }catch(AbcException ex){
            ex.printStackTrace();
        }
    }
}

使用JUnit 4 + Mockito 4.8.1编写测试时,调用mockStatic(Abc.class)会触发类加载,进而执行静态初始化块,导致抛出AbcException,无法完成Mock。

解决方案

方案一:使用PowerMock拦截静态初始化逻辑

Mockito本身无法在类加载阶段拦截静态初始化块,PowerMock通过修改类字节码可以实现这一点,步骤如下:

  1. 引入PowerMock相关依赖(适配JUnit 4):
    <!-- PowerMock JUnit 4 依赖 -->
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>2.0.9</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito2</artifactId>
        <version>2.0.9</version>
        <scope>test</scope>
    </dependency>
    
  2. 在测试类上添加PowerMock注解:
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(Abc.class)
    public class AbcTest {
        // 测试代码
    }
    
  3. 在@Before方法中抑制静态初始化块或目标方法:
    @Before
    public void setup() {
        // 抑制静态初始化块的执行
        PowerMockito.suppress(PowerMockito.staticInitializer(Abc.class));
        
        // 或者单独抑制fun()方法的执行
        // PowerMockito.suppress(PowerMockito.method(Abc.class, "fun"));
        
        // 现在可以正常创建静态Mock
        try (MockedStatic<Abc> abcMock = Mockito.mockStatic(Abc.class)) {
            // 配置Mock行为,比如让fun()不抛出异常
            abcMock.when(Abc::fun).doNothing();
        }
    }
    

方案二:重构源码(推荐)

如果允许修改业务代码,建议将静态初始化块中的逻辑抽离为可控制的初始化方法,避免类加载时自动执行风险逻辑:
修改后的Abc类:

class Abc{
    static void fun() throws AbcException{
        // 原有业务逻辑
    }
    
    // 手动初始化方法,替代静态初始化块
    public static void init() {
        try{
            fun();
        }catch(AbcException ex){
            ex.printStackTrace();
        }
    }
}

生产代码中在合适时机调用Abc.init()完成初始化,测试时可以先Mockfun()方法,再调用init(),避免类加载阶段抛出异常。

原因说明

Mockito的mockStatic方法需要先加载目标类,而JVM加载类时必然执行静态初始化块。此时fun()抛出异常会导致类加载失败,进而无法完成Mock。PowerMock通过字节码修改技术,在类加载时跳过静态初始化块的执行,从而解决这个问题。

内容的提问来源于stack exchange,提问作者Karthikeya H S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:20:28