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>())
...
}
Это уже публично:/
6 ответов
JUnit позволяет предоставлять правила через поле тестового класса или метод получения.
Тем не менее, в Kotlin вы аннотировали свойство, которое JUnit не распознает.
Вот возможные способы указать правило JUnit в Kotlin:
С помощью аннотированного метода получения
Начиная с M13, процессор аннотаций поддерживает цели аннотаций. Когда ты пишешь
@Rule
public val mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(javaClass<MainActivity>())
Тем не менее, аннотация будет использовать property
цель по умолчанию (невидима для Java).
Однако вы можете аннотировать свойство get, которое также является общедоступным и, таким образом, удовлетворяет требованиям JUnit для правила get:
@get:Rule
public val mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(javaClass<MainActivity>())
В качестве альтернативы, вы можете определить правило с помощью функции вместо свойства (достигая того же результата вручную, что и с @get:Rule
).
Через аннотированное публичное поле
Kotlin также позволяет бета-кандидату детерминистически компилировать свойства для полей в JVM, и в этом случае аннотации и модификаторы применяются к сгенерированному полю. Это делается с помощью Kotlin's @JvmField
аннотация собственности как ответ @jkschneider.
Примечание: обязательно добавьте префикс Rule
аннотация с @
символ, поскольку это теперь единственный поддерживаемый синтаксис для аннотаций, и избегать @publicField
как это скоро будет сброшено.
С Kotlin 1.0.0+ это работает:
@Rule @JvmField
val mActivityRule = ActivityTestRule(MainActivity::class.java)
Использовать этот:
@get:Rule
var mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)
Я согласен с @marci, возьмем этот пример, чтобы прояснить концепцию:
@get:Rule val tempFolder = TemporaryFolder() //apply @Rule annotation to property getter