Kotlin i nowa ActivityTestRule: Reguła @ musi być publiczna

264

Próbuję wykonać test interfejsu użytkownika dla mojej aplikacji na Androida w Kotlin. Ponieważ nowy system używa ActivityTestRule, nie mogę sprawić, by działał: kompiluje się poprawnie, aw czasie wykonywania otrzymuję:

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)

Oto jak zadeklarowałem mActivityRule:

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

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

   ...
}

To jest już publiczne: /

Geob-o-matic
źródło
3
Obecnie Kotlin nie obsługuje upubliczniania pól stanowiących podkład dla nieruchomości, ale pracujemy nad tym
Andrey Breslav
Czy śledzi to błąd?
Geob-o-matic

Odpowiedzi:

316

JUnit pozwala na dostarczanie reguł poprzez pole klasy testowej lub metodę gettera.

To , co zauważyłeś, to w Kotlinie właściwość , której JUnit nie rozpozna.

Oto możliwe sposoby określenia reguły JUnit w Kotlin:

Za pomocą metody gettera z adnotacjami

Od M13 procesor adnotacji obsługuje cele adnotacji . Kiedy piszesz

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

jednak adnotacja propertydomyślnie użyje obiektu docelowego (niewidocznego dla Javy).

Można jednak przypisać getterowi właściwość, która jest również publiczna, a zatem spełnia wymagania JUnit dla gettera reguł:

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

Alternatywnie możesz zdefiniować regułę za pomocą funkcji zamiast właściwości (osiągając ręcznie ten sam wynik, co w przypadku @get:Rule).

Poprzez opatrzone komentarzem pole publiczne

Kotlin pozwala również, ponieważ kandydat w wersji beta deterministycznie kompiluje właściwości do pól JVM, w którym to przypadku adnotacje i modyfikatory mają zastosowanie do wygenerowanego pola. Odbywa się to za pomocą @JvmFieldadnotacji o właściwościach Kotlina, na które odpowiedział @jkschneider .


Uwaga dodatkowa: pamiętaj, aby poprzedzać Ruleadnotację @znakiem, ponieważ jest to obecnie jedyna obsługiwana składnia adnotacji , i unikaj, @publicFieldponieważ wkrótce zostanie usunięta .

desseim
źródło
Czy to? Nadal pojawia się błąd i jest publiczny w M14 (0.14.449)
Geob-o-matic 10.10.15 o
wydaje się potrzebować @publicField, ale jest przestarzałe, więc spróbowałem lateinit, jak sugeruje IDE, ale potem szczeka na mnie, mówiąc, że lateinit można zastosować tylko do zmiennych (artykuł na blogu mówi inaczej ...)
Geob-o-matic
1
Zaktualizowałem moją odpowiedź;) Co do lateinit valtego, został on usunięty w M14, ponieważ nie w pełni wymusił niezmienność pola, patrz [post na blogu z wydaniem M14] (blog.jetbrains.com/kotlin/2015/10/kotlin- m14-is-out /).
desseim
Co to jest @get: adnotacja? To również nie działa w mojej sytuacji.
aleksandrbel
252

W przypadku Kotlin 1.0.0+ działa to:

@Rule @JvmField 
val mActivityRule = ActivityTestRule(MainActivity::class.java)
jkschneider
źródło
1
I rozwiązało to problem narzędzia do kłaczków, które skarżyło się, że społeczeństwo kwalifikowało się do reguły, ponieważ była zbędna.
Rob
Tak \ @JvmField ma kluczowe znaczenie lub użyj raczej \ @get: Reguła
Michał Ziobro
Działa tylko na końcowych polach. Nie będzie działać dla reguły takiej jak var wireMockRule = WireMockRule(wireMockConfig().dynamicPort()).
Abhijit Sarkar
17

Użyj tego:

@get:Rule
var mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)
Zahidur Rahman Faisal
źródło
Chcesz dodać wyjaśnienie?
peterchaula
12

Z Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get
Janin
źródło
To nie daje odpowiedzi na pytanie. Gdy zdobędziesz wystarczającą reputację , będziesz mógł komentować dowolny post ; zamiast tego podaj odpowiedzi, które nie wymagają wyjaśnienia od pytającego . - Z recenzji
Jignesh Ansodariya
10
@JigneshAnsodariya - Sprawdziłem, a ta odpowiedź stanowi odpowiedź na to, o co pytano. Więcej informacji na temat tego, jak to działa, można znaleźć pod następującym linkiem - kotlinlang.org/docs/reference/…
Praveer Gupta
Istnieje problem z tym podejściem. Jeśli chcesz uzyskać dostęp do testowanego działania (na przykład: assertTrue (activityRule.activity.isFinishing)), zostanie wywołany moduł pobierania właściwości, tworząc w ten sposób nową regułę. W takim przypadku activityRule.activity będzie miało wartość NULL.
makovkastar
0

Zamiast tego @Rulepowinieneś użyć @get:Rule.

Marci
źródło