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

不使用Powermock时如何通过JUnit5与Mockito抑制静态初始化

Mockito Mock静态类跳过静态初始化块实现方案

问题说明

  • 基于JUnit 5 + 原生Mockito框架做单元测试时,使用MockedStaticMock包含静态初始化块(static {})的类,默认会触发静态块逻辑执行
  • 实现约束:禁止引入Powermock等第三方Mock扩展
  • 目标:Mock目标类时不执行静态初始化块内的逻辑

复现代码

待Mock目标类

public class StaticUtils {
    static {
        // 测试时不希望执行该段初始化逻辑
        System.out.println("StaticUtils Initlizling...........");
    }

    private StaticUtils() {}

    public static List<Integer> range(int start, int end) {
        return IntStream.range(start, end)
          .boxed()
          .collect(Collectors.toList());
    }

    public static String name() {
        return "Baeldung";
    }
}

初始测试代码

运行该测试时控制台会打印静态块中的初始化日志,证明静态块被触发执行:

@ExtendWith(MockitoExtension.class)
class MockedStaticUnitTest {

    @Test
    void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
        // 注意:这行代码会提前触发类加载,导致静态块执行
        assertEquals(StaticUtils.name(), "Baeldung");

        try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
            utilities.when(StaticUtils::name).thenReturn("Eugen");
            assertEquals(StaticUtils.name(), "Eugen");
        }

        assertEquals(StaticUtils.name(), "Baeldung");
    }
}

实现步骤

  • 升级Mockito版本至3.12.0及以上,该版本在inline mock maker中新增了跳过类初始化的配置能力
  • 调用mockStatic方法时,传入Mockito.withSettings().noClassInit()作为Mock配置参数,告知Mockito创建Mock时不要触发类初始化
  • 移除mockStatic执行前所有对目标类静态成员、方法的直接引用,避免JVM提前加载类导致静态块执行

修改后可正常运行的测试代码

@ExtendWith(MockitoExtension.class)
class MockedStaticUnitTest {

    @Test
    void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
        // 传入noClassInit配置,跳过类初始化,不会触发静态块
        try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(
                StaticUtils.class,
                Mockito.withSettings().noClassInit()
        )) {
            // Stub静态方法返回值
            utilities.when(StaticUtils::name).thenReturn("Eugen");
            assertEquals(StaticUtils.name(), "Eugen");

            // 如需部分静态方法走真实逻辑,单独配置即可
            utilities.when(() -> StaticUtils.range(1,3)).thenCallRealMethod();
            assertEquals(StaticUtils.range(1,3), List.of(1,2));
        }
    }
}

注意事项

  • 该方案完全基于原生Mockito能力实现,无需引入任何额外第三方依赖
  • noClassInit()配置仅在目标类尚未被JVM加载初始化时生效,必须确保mockStatic调用前没有任何代码触发目标类的加载
  • 配置noClassInit()后,未手动Stub的静态方法不会执行真实逻辑,默认返回对应类型的默认值(null、0、false等),需要走真实逻辑的方法必须单独配置thenCallRealMethod()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:36:24