JUnit 5 Extensions在Kotlin中使用@RegisterExtension报错的解决方案咨询
解决Kotlin中JUnit 5 @RegisterExtension非静态字段访问权限问题
问题背景
Java版本的JUnit 5扩展代码可以正常运行:
@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class OtherTest { @RegisterExtension MyExtension myExtension = new MyExtension(); @Test void myTest() { System.out.println("my test"); } }
但对应的Kotlin版本运行时抛出异常:
org.junit.platform.commons.PreconditionViolationException: Failed to register extension via @RegisterExtension field [private org.example.MyExtension org.example.SomethingTest.myExtension]: field must not be private.
at app//org.junit.platform.commons.util.Preconditions.condition(Preconditions.java:296)
即使给字段加上open和var也无法解决——通过javap反编译可以看到,Kotlin默认会将字段设为私有,仅通过getter/setter暴露:
public class org.example.SomethingTest { public org.example.SomethingTest(); public final org.example.Something getSomething(); public final org.example.MyExtension getMyExtension(); public final void setMyExtension(org.example.MyExtension); public final void test do something(); }
目前用伴生对象加@JvmField可以规避,但不想使用静态字段,寻求其他方案。
扩展类代码如下:
class MyExtension : BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback { override fun beforeAll(context: ExtensionContext?) { println("beforeAll called") } override fun afterAll(context: ExtensionContext?) { println("afterAll called") } override fun beforeEach(context: ExtensionContext?) { println("beforeEach called") } override fun afterEach(context: ExtensionContext?) { println("afterEach called") } }
解决方案
直接给非静态的@RegisterExtension字段添加@JvmField注解,让Kotlin将字段直接暴露为public,而不是生成私有字段+访问器:
@TestInstance(TestInstance.Lifecycle.PER_CLASS) open class SomethingTest { val something = Something() @JvmField @RegisterExtension var myExtension = MyExtension() @Test fun `test do something`() { assert(something.doSomething()) } }
原理说明
@JvmField注解会告诉Kotlin编译器不要为该字段生成getter/setter方法,而是将字段直接编译为public非私有的成员变量,完全符合JUnit 5对@RegisterExtension字段的要求(非私有、结合PER_CLASS生命周期时可以是非静态)。- 这样既保留了非静态字段的特性,又让JUnit可以直接访问到该字段完成扩展注册,无需依赖静态伴生对象。
内容的提问来源于stack exchange,提问作者Kurt
相关产品推荐
相关产品推荐

