Kotlin 和新的 ActivityTestRule :@Rule 必须是 public

Kotlin and new ActivityTestRule : The @Rule must be public

我正尝试在 Kotlin 中对我的 android 应用程序进行 UI 测试。由于新系统使用 ActivityTestRule,我无法让它工作:它编译正确,并且在运行时,我得到:

java.lang.Exception: The @Rule 'mActivityRule' must be public.
    at org.junit.internal.runners.rules.RuleFieldValidator.addError(RuleFieldValidator.java:90)
    at org.junit.internal.runners.rules.RuleFieldValidator.validatePublic(RuleFieldValidator.java:67)
    at org.junit.internal.runners.rules.RuleFieldValidator.validateField(RuleFieldValidator.java:55)
    at org.junit.internal.runners.rules.RuleFieldValidator.validate(RuleFieldValidator.java:50)
    at org.junit.runners.BlockJUnit4ClassRunner.validateFields(BlockJUnit4ClassRunner.java:170)
    at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.ParentRunner.validate(ParentRunner.java:344)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:74)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:55)
    at android.support.test.internal.runner.junit4.AndroidJUnit4ClassRunner.<init>(AndroidJUnit4ClassRunner.java:38)
    at android.support.test.runner.AndroidJUnit4.<init>(AndroidJUnit4.java:36)
    at java.lang.reflect.Constructor.constructNative(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
    at android.support.test.internal.runner.junit4.AndroidAnnotatedBuilder.buildAndroidRunner(AndroidAnnotatedBuilder.java:57)
    at android.support.test.internal.runner.junit4.AndroidAnnotatedBuilder.runnerForClass(AndroidAnnotatedBuilder.java:45)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runner.Computer.getRunner(Computer.java:38)
    at org.junit.runner.Computer.runnerForClass(Computer.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:98)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:84)
    at org.junit.runners.Suite.<init>(Suite.java:79)
    at org.junit.runner.Computer.getSuite(Computer.java:26)
    at android.support.test.internal.runner.TestRequestBuilder.classes(TestRequestBuilder.java:691)
    at android.support.test.internal.runner.TestRequestBuilder.build(TestRequestBuilder.java:654)
    at android.support.test.runner.AndroidJUnitRunner.buildRequest(AndroidJUnitRunner.java:329)
    at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:226)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1584)

这是我声明 mActivityRule 的方式:

RunWith(javaClass<AndroidJUnit4>())
LargeTest
public class RadisTest {

    Rule
    public val mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(javaClass<MainActivity>())

   ...
}

已经是public:/

对于 Kotlin 1.0.0+,这有效:

@Rule @JvmField 
val mActivityRule = ActivityTestRule(MainActivity::class.java)

JUnit 允许通过测试 class 字段或 getter 方法提供规则。

虽然你注释的是 Kotlin 中的 属性,但 JUnit 无法识别。

以下是在 Kotlin 中指定 JUnit 规则的可能方法:

通过带注释的 getter 方法

From M13, the annotation processor supports annotation targets。 当你写

@Rule
public val mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(javaClass<MainActivity>())

尽管如此,注释将默认使用 property 目标(对 Java 不可见)。

但是,您可以注释 属性 getter,这也是 public,因此满足规则 getter:

的 JUnit 要求
@get:Rule
public val mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(javaClass<MainActivity>())

或者,您可以使用函数而不是 属性 来定义规则(手动获得与 @get:Rule 相同的结果)。

通过带注释的 public 字段

Kotlin 还允许 since the beta candidate to deterministically compile properties to fields on the JVM, in which case the annotations and modifiers apply to the generated field. This is done using Kotlin's @JvmField property annotation as .


旁注:请务必在 Rule 注释前加上 @ 字符,因为它现在是 the only supported syntax for annotations, and avoid @publicField as it will soon be dropped.

使用 Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get

使用这个:

@get:Rule
var mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)

而不是 @Rule ,你应该使用 @get:Rule.