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


264

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

   ...
}

它已经公开了:/


3
目前,Kotlin不支持公开支持房地产的领域,但我们正在努力
Andrey Breslav 2015年

是否有跟踪此错误?
Geob-o-matic 2015年

Answers:


316

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

您注释的是Kotlin中的一个属性,但JUnit无法识别。

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

通过带注释的吸气剂方法

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

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

但是,注释将property默认使用目标(Java不可见)。

但是,您可以注释属性获取器,该属性也是公共的,因此可以满足规则获取器的JUnit要求:

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

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

通过带注释的公共场所

Kotlin还允许从beta候选版本起确定性地将属性编译到JVM上的字段,在这种情况下,注释和修饰符将应用于生成的字段。这是通过使用@jkschneider回答的 Kotlin @JvmField属性注释来完成的


旁注:请确保在Rule注释@前面加上一个字符,因为它是注释唯一受支持的语法,请避免@publicField使用它,因为它将很快被删除


可以?我仍然收到该错误,并且它与M14(0.14.449)公开
-Geob-o-matic

似乎需要@publicField,但已弃用,因此我按IDE的建议尝试了Lateinit,但随后它吠叫我说Lateinit仅可用于可变的(博客文章说否则……)
Geob-o-matic

1
更新了我的回答;)至于lateinit val,由于未完全强制执行字段的不变性,因此已在M14中删除,请参阅[M14发布博客文章](blog.jetbrains.com/kotlin/2015/10/kotlin- m14-is-out /)。
desseim 2015年

什么是@get:批注?在我的情况下,它也不起作用。
aleksandrbel

252

使用Kotlin 1.0.0+,可以使用:

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

1
它解决了皮棉工具抱怨公众在规则上是限定词是多余的问题。
罗布

是\ @JvmField是至关重要的或使用的,而\ @get:规则
米哈尔Ziobro

仅适用于最终字段。不适用于像这样的规则var wireMockRule = WireMockRule(wireMockConfig().dynamicPort())
Abhijit Sarkar


12

使用Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get

这不能为问题提供答案。一旦您拥有足够的声誉,您就可以在任何帖子中发表评论;相反,请提供不需要问询者澄清的答案。- 评分
Jignesh Ansodariya

10
@JigneshAnsodariya-我检查了一下,这个答案提供了所要求的答案。这是如何的更多信息工作可以通过以下链接找到- kotlinlang.org/docs/reference/...
Praveer古普塔

这种方法存在问题。如果要访问被测活动(例如:assertTrue(activityRule.activity.isFinishing)),则将调用属性getter,从而创建一个新规则。在这种情况下activityRule.activity将为null。
makovkastar

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.