Kotlin 和新的 ActivityTestRule :@Rule 必须是公开的

问题描述 投票:0回答:6

我正在尝试在 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$1.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>())

   ...
}

已经公开了:/

android testing android-espresso kotlin
6个回答
393
投票

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

您注释的内容在 Kotlin 中是一个 property,JUnit 无法识别。

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

通过带注释的 getter 方法

从 M13 开始,注释处理器支持注释目标。 当你写的时候

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

但是,注释默认情况下将使用

property
目标(对于 Java 不可见)。

但是,您可以注释属性 getter,它也是公共的,因此满足 JUnit 对规则 getter 的要求:

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

或者,您可以使用函数而不是属性来定义规则(手动实现与使用

@get:Rule
相同的结果)。

通过带注释的公共字段

Kotlin 还允许 从 beta 候选版开始 确定地将属性编译到 JVM 上的字段,在这种情况下,注释和修饰符适用于生成的字段。这是使用 Kotlin 的

@JvmField
属性注释来完成的,如@jkschneider回答的


旁注:请务必在

Rule
注释前添加
@
字符,因为它现在是 唯一支持的注释语法,并避免使用
@publicField
,因为它很快就会被删除


270
投票

对于 Kotlin 1.0.0+,这有效:

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

28
投票

使用这个:

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

23
投票

您应该使用

@Rule
,而不是
@get:Rule


12
投票

使用 Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get

0
投票

我同意@marci,用这个例子来阐明这个概念:

@get:Rule val tempFolder = TemporaryFolder() //apply @Rule annotation to property getter
© www.soinside.com 2019 - 2024. All rights reserved.