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: /

Geob-o-matic
sumber
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 .

desseim
sumber
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)
jkschneider
sumber
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
17

Gunakan ini:

@get:Rule
var mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)
Zahidur Rahman Faisal
sumber
Ingin menambahkan penjelasan?
peterchaula
12

Dengan Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get
janin
sumber
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.

Marci
sumber