Kotlin и новый ActivityTestRule: @Rule должен быть общедоступным

Я пытаюсь сделать тест интерфейса для моего приложения для Android в Kotlin. Поскольку новая система использует 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>())

   ...
}

Это уже публично:/

Ответ 1

JUnit позволяет предоставлять правила через поле тестового класса или метод получения.

Тем не менее, то, что вы аннотировали, в Kotlin - это свойство, которое JUnit не распознает.

Вот возможные способы указать правило JUnit в Kotlin:

С помощью аннотированного метода получения

Начиная с 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 вручную тот же результат, что и с @get:Rule).

Через аннотированное публичное поле

Kotlin также позволяет бета-кандидату детерминистически компилировать свойства для полей в JVM, и в этом случае аннотации и модификаторы применяются к сгенерированному полю. Это делается с @JvmField аннотации свойства Kotlin @JvmField на которую отвечает @jkschneider.


Примечание: обязательно добавьте в примечание к Rule символ @ поскольку теперь он является единственным поддерживаемым синтаксисом для аннотаций, и избегайте @publicField поскольку он скоро будет @publicField.

Ответ 2

С Kotlin 1.0.0+ это работает:

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

Ответ 3

С Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get

Ответ 4

Использовать этот:

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