不使用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
相关产品推荐
相关产品推荐

