Котлін та новий ActivityTestRule: @Rule повинен бути загальнодоступним


264

Я намагаюся зробити тест на інтерфейс користувача для свого додатка для Android у Котліні. Оскільки нова система, що використовує 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
Наразі Котлін не підтримує оприлюднення полів, які підтримують властивості, але ми працюємо над цим
Андрій Бреслав

Чи відстежують цю помилку?
Geob-o-matic

Відповіді:


316

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

Те, що ви помітили, є в Котліні власністю , яку JUnit не визнає.

Ось можливі способи вказати правило 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 також дозволяє з бета-кандидатом детерміновано компілювати властивості до полів JVM, і в цьому випадку анотації та модифікатори застосовуються до генерованого поля. Це робиться за допомогою @JvmFieldанотації властивостей Котліна, на яку відповів @jkschneider .


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


Робить це? Я все ще отримую помилку, і вона відкрита для M14 (0.14.449)
Geob-o-matic

Здається, потрібен @publicField, але він застарілий, тому я спробував латиніт, як це запропонував IDE, але потім він гавкає на мене, кажучи, що lateinit можна застосовувати лише на мутабелі (стаття в блозі говорить інакше ...)
Geob-o-matic

1
Оновлено мою відповідь;) Щодо цього lateinit val, він був видалений у M14, оскільки він не повністю застосував незмінність поля, див. [M14 blog blog release] (blog.jetbrains.com/kotlin/2015/10/kotlin- m14-виходить /).
дессеїм

Що таке @get: анотація? Це також не працює в моїй ситуації.
aleksandrbel

252

З Kotlin 1.0.0+, це працює:

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

1
І це вирішило проблему інструменту для ворсинок, нарікаючи, що громадськість є кваліфікованим за правилом, це зайве.
Роб

Так \ @ JvmField має вирішальне значення або скоріше скористайтеся \ @get: Правило
Michał

Працює лише на заключних полях. Не працюватиме як правило var wireMockRule = WireMockRule(wireMockConfig().dynamicPort()).
Абхіджіт Саркар


12

З Котліном 1.0.4:

val mActivityRule: ...
    @Rule get

Це не дає відповіді на запитання. Коли у вас буде достатня репутація, ви зможете коментувати будь-яку публікацію ; натомість надайте відповіді, які не потребують уточнення від запитувача . - З огляду
Jignesh Ansodariya

10
@JigneshAnsodariya - я зробив перевірку, і ця відповідь дає відповідь на запитання. Детальніше про те, як це працює, ви можете знайти за наступним посиланням - kotlinlang.org/docs/reference/…
Praveer Gupta

У цьому підході є проблема. Якщо ви хочете отримати доступ до тестуваної активності (наприклад: assertTrue (ActivityRule.activity.isFinishing)), виклику властивості буде викликано, створивши нове правило. У цьому випадку ActivityRule.activity буде нульовим.
makovkastar

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.