Kotlin dan ActivityTestRule baru: @Rule harus bersifat publik


264

Saya mencoba membuat tes UI untuk aplikasi Android saya di Kotlin. Karena sistem baru menggunakan ActivityTestRule, saya tidak bisa membuatnya bekerja: ia mengkompilasi dengan benar, dan saat runtime, saya mendapatkan:

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)

Inilah cara saya mendeklarasikan mActivityRule:

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

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

   ...
}

Sudah publik: /


3
Saat ini, Kotlin tidak mendukung pembuatan bidang yang mendukung properti, tetapi kami sedang mengusahakannya
Andrey Breslav

Apakah ada bug yang melacak ini?
Geob-o-matic

Jawaban:


316

JUnit memungkinkan penyediaan aturan melalui bidang kelas uji atau metode pengambil.

Apa yang Anda anotasi di Kotlin adalah properti , yang JUnit tidak akan kenal.

Berikut adalah cara yang mungkin untuk menentukan aturan JUnit di Kotlin:

Melalui metode pengambil beranotasi

Dari M13 , prosesor anotasi mendukung target anotasi . Ketika Anda menulis

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

meskipun, anotasi akan menggunakan propertytarget secara default (tidak terlihat oleh Java).

Anda dapat membuat anotasi pengambil properti, yang juga publik dan dengan demikian memenuhi persyaratan JUnit untuk pengambil aturan:

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

Atau, Anda bisa mendefinisikan aturan dengan fungsi alih-alih properti (mencapai hasil yang sama dengan secara manual @get:Rule).

Melalui bidang publik beranotasi

Kotlin juga memungkinkan karena kandidat beta untuk secara kompilasi mengkompilasi properti ke bidang pada JVM, dalam hal ini anotasi dan pengubah berlaku untuk bidang yang dihasilkan. Ini dilakukan dengan menggunakan @JvmFieldanotasi properti Kotlin seperti dijawab oleh @jkschneider .


Catatan sisi: pastikan untuk mengawali Ruleanotasi dengan @karakter karena sekarang hanya sintaks yang didukung untuk anotasi , dan hindari @publicFieldkarena akan segera dihapus .


Melakukannya? Saya masih mendapatkan kesalahan dan bersifat umum dengan M14 (0.14.449)
Geob-o-matic

tampaknya membutuhkan @publicField, tetapi sudah usang, jadi saya mencoba lateinit seperti yang disarankan oleh IDE, tetapi kemudian menggonggong pada saya mengatakan lateinit dapat diterapkan hanya pada bisa berubah (artikel blog mengatakan sebaliknya ...)
Geob-o-matic

1
Diperbarui jawaban saya;) Adapun lateinit val, telah dihapus di M14 karena tidak sepenuhnya menegakkan keabadian lapangan, lihat [posting blog rilis M14] (blog.jetbrains.com/kotlin/2015/10/10/kotlin- m14-is-out /).
desseim

Apa itu @get: anotasi? Itu juga tidak berfungsi dalam situasi saya.
aleksandrbel

252

Dengan Kotlin 1.0.0+, ini berfungsi:

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

1
Dan itu memecahkan masalah alat serat mengeluh bahwa masyarakat memenuhi syarat pada aturan itu berlebihan.
Rob

Ya \ @JvmField sangat penting atau gunakan agak \ @get: Aturan
Michał Ziobro

Hanya bekerja pada bidang terakhir. Tidak akan bekerja untuk aturan seperti var wireMockRule = WireMockRule(wireMockConfig().dynamicPort()).
Abhijit Sarkar


12

Dengan Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get

Ini tidak memberikan jawaban untuk pertanyaan itu. Setelah memiliki reputasi yang cukup, Anda dapat mengomentari setiap pos ; alih-alih, berikan jawaban yang tidak memerlukan klarifikasi dari penanya . - Dari Ulasan
Jignesh Ansodariya

10
@JigneshAnsodariya - Saya melakukan pengecekan dan jawaban ini memberikan jawaban atas apa yang ditanyakan. Informasi lebih lanjut tentang bagaimana ini bekerja dapat ditemukan di tautan berikut - kotlinlang.org/docs/reference/…
Praveer Gupta

Ada masalah dengan pendekatan ini. Jika Anda ingin mengakses aktivitas yang sedang diuji (misalnya: assertTrue (activityRule.activity.isFinishing)), pengambil properti akan dipanggil, sehingga membuat aturan baru. Dalam hal ini activityRule.activity akan menjadi nol.
makovkastar

0

Alih-alih @Rule, Anda harus menggunakan @get:Rule.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.