Kotlin và ActivityTestRule mới: @Rule phải được công khai


264

Tôi đang cố gắng thực hiện kiểm tra giao diện người dùng cho ứng dụng Android của mình trong Kotlin. Vì hệ thống mới sử dụng ActivityTestRule, tôi không thể làm cho nó hoạt động: nó biên dịch chính xác và trong thời gian chạy, tôi nhận được:

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)

Đây là cách tôi khai báo mActivityRule:

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

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

   ...
}

Nó đã được công khai: /


3
Hiện tại, Kotlin không hỗ trợ làm cho các trường đang sao lưu các thuộc tính công khai, nhưng chúng tôi đang làm việc trên đó
Andrey Breslav

Có một lỗi theo dõi này?
Geob-o-matic

Câu trả lời:


316

JUnit cho phép cung cấp các quy tắc thông qua trường lớp kiểm tra hoặc phương thức getter.

Những gì bạn chú thích là trong một tài sản mặc dù, mà JUnit sẽ không nhận ra.

Dưới đây là các cách có thể để chỉ định quy tắc JUnit trong Kotlin:

Thông qua một phương thức getter chú thích

Từ M13 , bộ xử lý chú thích hỗ trợ các mục tiêu chú thích . Khi bạn viết

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

mặc dù, chú thích sẽ sử dụng propertyđích theo mặc định (không hiển thị với Java).

Tuy nhiên, bạn có thể chú thích bộ nhận tài sản, cũng là công khai và do đó đáp ứng các yêu cầu của JUnit cho bộ lấy quy tắc:

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

Ngoài ra, bạn có thể xác định quy tắc bằng một hàm thay vì thuộc tính (đạt được kết quả tương tự như với @get:Rule).

Thông qua một lĩnh vực công cộng có chú thích

Kotlin cũng cho phép kể từ khi ứng cử viên beta biên dịch các thuộc tính một cách xác định vào các trường trên JVM, trong trường hợp đó các chú thích và sửa đổi áp dụng cho trường được tạo. Điều này được thực hiện bằng cách sử dụng @JvmFieldchú thích thuộc tính của Kotlin như được trả lời bởi @jkschneider .


Lưu ý bên lề: hãy chắc chắn đặt tiền tố Rulechú thích bằng một @ký tự vì giờ đây nó là cú pháp được hỗ trợ duy nhất cho chú thích và tránh @publicFieldvì nó sẽ sớm bị loại bỏ .


Phải không? Tôi vẫn nhận được lỗi và nó được công khai với M14 (0.14.449)
Geob-o-matic

Dường như cần @publicField, nhưng nó không được chấp nhận, vì vậy tôi đã thử dùng lateinit theo đề xuất của IDE, nhưng sau đó nó nói với tôi rằng lateinit chỉ có thể được áp dụng trên mutable (bài viết trên blog nói cách khác)
Geob-o-matic

1
Đã cập nhật câu trả lời của tôi;) Về phần lateinit val, nó đã bị xóa trong M14 vì nó không thực thi đầy đủ tính bất biến của trường, xem [bài đăng blog phát hành M14] (blog.jetbrains.com/kotlin/2015/10/kotlin- m14-is-out /).
desseim

@Get: chú thích là gì? Nó cũng không hoạt động trong tình huống của tôi.
aleksandrbel

252

Với Kotlin 1.0.0+, điều này hoạt động:

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

1
Và nó đã giải quyết vấn đề của công cụ lint phàn nàn rằng công chúng là vòng loại theo quy tắc là dư thừa.
Rob

Có \ @JvmField rất quan trọng hoặc sử dụng thay thế \ @get: Quy tắc
Michał Ziobro

Chỉ hoạt động trên các lĩnh vực cuối cùng. Sẽ không làm việc cho một quy tắc như var wireMockRule = WireMockRule(wireMockConfig().dynamicPort()).
Abhijit Sarkar

17

Dùng cái này:

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

Quan tâm để thêm một lời giải thích?
peterchaula

12

Với Kotlin 1.0.4:

val mActivityRule: ...
    @Rule get

Điều này không cung cấp một câu trả lời cho câu hỏi. Một khi bạn có đủ danh tiếng, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào ; thay vào đó, cung cấp câu trả lời không yêu cầu làm rõ từ người hỏi . - Từ đánh giá
Jignesh Ansodariya

10
@JigneshAnsodariya - Tôi đã kiểm tra và câu trả lời này cung cấp câu trả lời cho những gì đã được hỏi. Thông tin thêm về cách thức hoạt động của nó có thể được tìm thấy tại liên kết sau - kotlinlang.org/docs/reference/ mẹo
Praveer Gupta 4/11/2016

Có một vấn đề với phương pháp này. Nếu bạn muốn truy cập vào hoạt động được thử nghiệm (ví dụ: assertTrue (ActivityRule.activity.isFinishing)), getter thuộc tính sẽ được gọi, do đó tạo ra một quy tắc mới. Trong trường hợp này hoạt độngRule.activity sẽ là null.
makovkastar

0

Thay vì @Rule, bạn nên sử dụng @get:Rule.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.