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

Posted

技术标签:

【中文标题】Kotlin 和新的 ActivityTestRule :@Rule 必须是公开的【英文标题】:Kotlin and new ActivityTestRule : The @Rule must be public 【发布时间】:2015-07-08 19:39:12 【问题描述】:

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

   ...

它已经公开了:/

【问题讨论】:

目前,Kotlin 不支持公开支持属性的字段,但我们正在努力 是否有跟踪此问题的错误? youtrack.jetbrains.com/issue/KT-3441 【参考方案1】:

您应该使用 @get:Rule 而不是 @Rule

【讨论】:

【参考方案2】:

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

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

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

通过带注释的 getter 方法

From M13,注解处理器supports annotation targets。 当你写

@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 还允许since the beta candidate 确定性地将属性编译为 JVM 上的字段,在这种情况下,注释和修饰符将应用于生成的字段。这是使用 Kotlin 的 @JvmField 属性注释作为 answered by @jkschneider 完成的。


旁注:确保在 Rule 注释前加上 @ 字符,因为它现在是 the only supported syntax for annotations,并避免使用 @publicField,因为它是 will soon be dropped。

【讨论】:

是吗?我仍然收到错误消息,它在 M14 (0.14.449) 中是公开的 似乎需要@publicField,但它已被弃用,所以我按照IDE的建议尝试了lateinit,但后来它对我咆哮说lateinit只能应用于可变(博客的文章另有说明......) 更新了我的答案 ;) 至于lateinit val,它已在 M14 中删除,因为它没有完全强制该字段的不变性,请参阅 [M14 发布博客文章](blog.jetbrains .com/kotlin/2015/10/kotlin-m14-is-out/)。 什么是@get:注解?它也不适用于我的情况。【参考方案3】:

使用这个:

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

【讨论】:

想添加解释吗?【参考方案4】:

使用 Kotlin 1.0.0+,这可行:

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

【讨论】:

解决了 lint 工具抱怨 public is qualifier on the rule 是多余的问题。 是的 \@JvmField 是至关重要的或使用 \@get:Rule 仅适用于最终字段。不适用于 var wireMockRule = WireMockRule(wireMockConfig().dynamicPort()) 之类的规则。【参考方案5】:

使用 Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get

【讨论】:

这并没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review @JigneshAnsodariya - 我做了检查,这个答案提供了对所问问题的答案。有关其工作原理的更多信息,请访问以下链接 - kotlinlang.org/docs/reference/… 这种方法有问题。如果要访问被测活动(例如:assertTrue(activityRule.activity.isFinishing)),将调用属性 getter,从而创建新规则。在这种情况下,activityRule.activity 将为空。

以上是关于Kotlin 和新的 ActivityTestRule :@Rule 必须是公开的的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2017 和新的 .csproj InternalsVisibleTo

CORS 和新的 ASPNET5

下载所有可用的(和新的)文件

Google Play 游戏、Firebase 和新的 Google 登录

终总结,新的里程和新的开始

UINavigationBar 和新的 iOS 5+ 外观 API - 如何提供两个背景图像?