JUnit 5中@BeforeAll与@Mock静态字段初始化顺序问题
静态Mock在@BeforeAll中失效的原因分析
问题场景
第一种配置(执行时mockedInstanceReference为空):
@ExtendWith(MockitoExtension.class) TestClass{ @Mock private static ClassB classBInstance; @BeforeAll static void setup(){ MockedStatic<ClassA> mockedStatic = mockStatic(ClassA.class); mockedStatic.when(() -> ClassA.someMethod(ClassB.class)).thenReturn(classBInstance); } @Test void testMethod(){ var mockedInstanceReference = ClassA.someMethod(ClassB.class); } }
第二种配置(能正常获取Mock引用):
@ExtendWith(MockitoExtension.class) TestClass{ @Mock private static ClassB classBInstance; @Test void testMethod(){ MockedStatic<ClassA> mockedStatic = mockStatic(ClassA.class); mockedStatic.when(() -> ClassA.someMethod(ClassB.class)).thenReturn(classBInstance); var mockedInstanceReference = ClassA.someMethod(ClassB.class); } }
核心原因:JUnit 5与Mockito的执行顺序差异
问题出在静态@Mock字段的初始化时机和@BeforeAll方法的执行顺序上,具体流程如下:
第一种配置的执行流程
- 测试类加载时,静态字段
classBInstance被Java默认规则初始化为null - JUnit 5优先执行标注了
@BeforeAll的静态方法setup - 此时Mockito还未完成对静态
@Mock字段的注入,classBInstance仍然是null,所以thenReturn(classBInstance)实际上是把静态方法的返回值设置为null - 后续执行
testMethod时,调用ClassA.someMethod自然得到null
第二种配置的执行流程
- 测试类加载时,静态字段
classBInstance先被初始化为null - 在执行
@Test方法之前,MockitoExtension已经完成了所有@Mock字段(包括静态字段)的注入,classBInstance被赋值为有效的Mock实例 - 进入
testMethod后,设置静态Mock的返回值时,使用的是已经初始化完成的Mock实例,所以调用ClassA.someMethod能拿到正确的Mock引用
补充说明
MockitoExtension对静态@Mock字段的注入动作,是在所有@BeforeAll方法执行之后,第一个@Test方法执行之前完成的。这就是为什么把静态Mock的配置放在@Test方法里能正常工作,放在@BeforeAll里就会拿到null。
内容的提问来源于stack exchange,提问作者HowToTellAChild
相关产品推荐
相关产品推荐

