父类中@BeforeAll方法未执行,此为预期行为还是使用错误?
问题分析与解决
这其实是JUnit 5的预期行为,核心原因是你没注意到@TestInstance注解的继承规则,我来给你拆解清楚:
为什么父类的@BeforeAll方法没执行?
- JUnit 5的
@TestInstance注解默认不会被子类继承(它没有标注@Inherited元注解),所以你的子类MyAppTest没有显式指定生命周期时,会使用默认的PER_METHOD模式。 - 在
PER_METHOD模式下,@BeforeAll注解的方法必须是静态方法(或者类被标注为PER_CLASS)。但你父类里的setStatus()是实例方法——这是因为父类用了PER_CLASS模式,允许实例方法作为@BeforeAll。 - 子类处于
PER_METHOD模式时,JUnit会忽略非静态的@BeforeAll方法,所以父类的setStatus()根本不会被调用,status自然还是初始的false,导致测试失败。
两种可行的解决方案
方案一:给子类也加上PER_CLASS注解
直接在子类上显式标注@TestInstance(TestInstance.Lifecycle.PER_CLASS),让子类和父类保持相同的生命周期,这样父类的实例方法@BeforeAll就会被正常执行:
@TestInstance(TestInstance.Lifecycle.PER_CLASS) class MyAppTest : TestBase() { @Test fun testStatus() { assertTrue(status) // 现在测试会成功通过 } }
方案二:把父类的@BeforeAll方法改为静态方法
如果不想改变子类的生命周期,可以把父类的setStatus()改成静态方法(Kotlin里用companion object配合@JvmStatic实现),同时把status也改成静态变量:
open class TestBase { companion object { var status: Boolean = false @BeforeAll @JvmStatic fun setStatus() { status = true } } } class MyAppTest : TestBase() { @Test fun testStatus() { assertTrue(TestBase.status) // 测试成功 } }
内容的提问来源于stack exchange,提问作者user2462794
相关产品推荐
相关产品推荐

