用 Espresso 测试 recyclerView,如何执行点击或断言

Testing recyclerView with Espresso, how to perform click or make assertions

最近我需要测试 RecyclerView,但我很难用它做任何事情。

首先,通过为我们提供位于 espresso-contrib 的 RecyclerViewActions,我了解到 Espresso 已经是 "supporting" RecyclerViews。所以我决定使用它,我的依赖项如下所示:

dependencies {

    androidTestCompile 'junit:junit:4.12'
    androidTestCompile 'com.squareup.spoon:spoon-client:1.2.1'
    androidTestCompile 'com.jraska:falcon-spoon-compat:0.3.1'
    androidTestCompile 'com.android.support:support-annotations:23.1.1'

    androidTestCompile 'com.android.support.test:runner:0.4.1'
    androidTestCompile 'com.android.support.test:rules:0.4.1'
    androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.1'

    androidTestCompile "org.mockito:mockito-core:1.10.19"
    androidTestCompile "com.google.dexmaker:dexmaker:1.2"
    androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
}

但是因为只有我在将 espresso-core 更改为 espresso-contrib 后才尝试 运行 我的测试。我可以看到这个错误:

Test running failed: Instrumentation run failed due to 'java.lang.IncompatibleClassChangeError'

我试着 google 解决了。我看到很多主题,人们给出了 this one 之类的回复。所以我排除了 appcompat、supportv4 和 recyclerview-v7。像那样:

   androidTestCompile ('com.android.support.test.espresso:espresso-contrib:2.2.1') {
        exclude group: 'com.android.support', module: 'appcompat'
        exclude group: 'com.android.support', module: 'support-v4'
        exclude module: 'recyclerview-v7'
    }

测试开始了,但是...我无法使用任何 RecyclerViewActions。因为排除recyclerview-v7后就没有方法了,网上看到的几乎都是推荐的。当我尝试使用 - RecyclerViewActions.actionOnItemAtPosition - 对我来说是核心的方法时,我收到此错误:

java.lang.NoSuchMethodError: No virtual method findViewHolderForPosition(I)Landroid/support/v7/widget/RecyclerView$ViewHolder; in class Landroid/support/v7/widget/RecyclerView; or its super classes (declaration of 'android.support.v7.widget.RecyclerView' appears in /data/app/com.myapp.debug1-1/base.apk)
at android.support.test.espresso.contrib.RecyclerViewActions$ActionOnItemAtPositionViewAction.perform(RecyclerViewActions.java:288)
at android.support.test.espresso.ViewInteraction.run(ViewInteraction.java:144)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

所以我宁愿拥有这个 recyclerview-v7 而不是排除它。我将我的 espresso-contrib 导入修改为:

 androidTestCompile ('com.android.support.test.espresso:espresso-contrib:2.2.1') {
        exclude group: 'com.android.support', module: 'appcompat'
        exclude group: 'com.android.support', module: 'support-v4'
    }

再次测试 运行 但是...我在测试期间某处出错:

android.view.InflateException: Binary XML file line #36: Error inflating class android.support.design.widget.NavigationView

所以我在 gradle:

中使用了最新的库
 compile 'com.android.support:appcompat-v7:23.1.1'
 compile 'com.android.support:support-v13:23.1.1'
 compile 'com.android.support:cardview-v7:23.1.1'
 compile 'com.android.support:design:23.1.1'

并且 NavigationView 使用最新的 RecyclerView 23.1.1。我试图找出问题所在,所以我在控制台中使用 ./gradlew app:dependencies 显示 espresso-contrib 的依赖关系,我可以看到:

 +--- com.android.support.test.espresso:espresso-contrib:2.2.1
|    +--- com.android.support.test.espresso:espresso-core:2.2.1
|    |    +--- com.squareup:javawriter:2.1.1
|    |    +--- com.android.support.test:runner:0.4.1 (*)
|    |    +--- com.android.support.test:rules:0.4.1 (*)
|    |    +--- javax.inject:javax.inject:1
|    |    +--- org.hamcrest:hamcrest-library:1.3
|    |    |    \--- org.hamcrest:hamcrest-core:1.3
|    |    +--- org.hamcrest:hamcrest-integration:1.3
|    |    |    \--- org.hamcrest:hamcrest-library:1.3 (*)
|    |    +--- com.google.code.findbugs:jsr305:2.0.1
|    |    +--- javax.annotation:javax.annotation-api:1.2
|    |    \--- com.android.support.test.espresso:espresso-idling-resource:2.2.1
|    +--- com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.0
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:recyclerview-v7:23.0.1
|         \--- com.android.support:support-annotations:23.0.1 -> 23.1.1

好的,最新的 espresso-contrib-2.2.1 使用的是 com.android.support:recyclerview-v7:23.0.1 - 不是最新版本的 recyclerView,它会导致错误。我决定通过添加以下内容在 espresso-contrib 中更新它:

 androidTestCompile 'com.android.support:recyclerview-v7:23.1.1'

我再次使用 app:dependencies,我可以看到变化:

\--- com.android.support:recyclerview-v7:23.0.1 -> 23.1.1 (*)

我又开始测试了。而且 NavigationView 不再出现错误 - 我认为它已解决但是......出现另一个错误:

android.view.InflateException: Binary XML file line #21: Error inflating class android.support.v7.widget.Toolbar

现在我有点没思路了。当您查看 espresso-contrib 的依赖项时,我认为它没有使用任何可能使用工具栏的东西。工具栏是 appcompat-v7 的一部分,因此我尝试以与将 recyclerView 升级到最新版本相同的方式添加它。所以我添加:

androidTestCompile 'com.android.support:appcompat-v7:23.1.1'

但这对我没有帮助。我卡住了。

你遇到过这些问题吗?你有什么解决方法可以点击 recyclerView 吗?如何检查 recyclerView 中的项目是否有文本或类似的东西?我在网上找到的所有解决方案都使用方法:findViewHolderForPosition,排除 recyclerview-v7 模块后我无法使用。喜欢:

https://github.com/dannyroa/espresso-samples/tree/master/RecyclerView/app/src/androidTest/java/com/dannyroa/espresso_samples/recyclerview

https://gist.github.com/chemouna/00b10369eb1d5b00401b

或更多。

工具栏的问题是因为我在 app.gradle 文件中使用的一些库没有最新的 RecyclerView,所以我还需要添加:

compile 'com.android.support:appcompat-v7:23.1.1'

java.lang.NoSuchMethodError 的问题在我这边。 ProGuard 配置正在删除一些方法。