web-dev-qa-db-fra.com

Kotlin et new ActivityTestRule: la @Rule doit être publique

J'essaie de faire tester l'interface utilisateur de mon application Android dans Kotlin. Depuis le nouveau système utilisant ActivityTestRule, je ne peux pas le faire fonctionner: il se compile correctement, et à l'exécution, j'obtiens:

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)

Voici comment j'ai déclaré mActivityRule:

RunWith(javaClass<AndroidJUnit4>())
LargeTest
public class RadisTest {

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

   ...
}

C'est déjà public: /

233
Geob-o-matic

JUnit permet de fournir des règles via un champ de classe de test ou une méthode getter.

Ce que vous avez annoté est dans Kotlin une propriété que JUnit ne reconnaît pas.

Voici les manières possibles de spécifier une règle JUnit dans Kotlin:

Par une méthode getter annotée

à partir de M1 , le processeur d'annotation prend en charge les cibles d'annotation . Quand tu écris

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

cependant, l'annotation utilisera la cible property par défaut (non visible pour Java).

Vous pouvez toutefois annoter le getter de la propriété, qui est également public et satisfait donc aux exigences de JUnit pour un getter de règles:

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

Vous pouvez également définir la règle avec une fonction au lieu d'une propriété (obtenir manuellement le même résultat qu'avec _@get:Rule_).

À travers un champ public annoté

Kotlin permet également à depuis le candidat bêta de compiler de manière déterministe les propriétés des champs de la machine virtuelle, auquel cas les annotations et les modificateurs s’appliquent au champ généré. Ceci est fait en utilisant l'annotation de la propriété @JvmField de Kotlin en tant que répond par @jkschneider .


Note latérale: assurez-vous de préfixer l'annotation Rule avec un caractère _@_ tel qu'il est maintenant la seule syntaxe prise en charge pour les annotations , et évitez _@publicField_ - sera bientôt abandonné .

288
desseim

Avec Kotlin 1.0.0+, cela fonctionne:

@Rule @JvmField 
val mActivityRule = ActivityTestRule(MainActivity::class.Java)
236
jkschneider

Utilisez ceci:

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

Avec Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get
11
janin