Tests fail after Espresso 2 upgrade (failed: Instr

2019-01-18 04:35发布

问题:

After upgrading Espresso to version 2 none of my unit tests will run on pre-lollipop devices. See the trace below:

15:07:07.627 [WARN] [org.gradle.api.Project] Tests on Samsung Galaxy S3 - 4.3 - API 18 - 720x1280 - 4.3 failed: Instrumentation run failed due to 'java.lang.IllegalAccessError'
15:07:07.832 [WARN] [org.gradle.api.Project] 
com.android.builder.testing.ConnectedDevice > hasTests[Samsung Galaxy S3 - 4.3 - API 18 - 720x1280 - 4.3] FAILED 
15:07:07.832 [WARN] [org.gradle.api.Project] No tests found.
15:07:07.834 [DEBUG] [org.gradle.api.Project] DeviceConnector 'Samsung Galaxy S3 - 4.3 - API 18 - 720x1280 - 4.3': uninstalling com.nordstrom.fla.test
15:07:08.252 [DEBUG] [org.gradle.api.Project] DeviceConnector 'Samsung Galaxy S3 - 4.3 - API 18 - 720x1280 - 4.3': uninstalling com.nordstrom.fla
15:07:08.666 [INFO] [org.gradle.api.Project] deleteDir(/Users/graemeharnish/workspace/fla-android/app/build/outputs/reports/androidTests/connected) returned: true
15:07:08.702 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Finished executing task ':app:connectedAndroidTest'
15:07:08.702 [LIFECYCLE] [class org.gradle.TaskExecutionLogger] :app:connectedAndroidTest FAILED

The stack trace is equally unhelpful

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:connectedAndroidTest'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:305)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)

My gradle dependencies

dependencies {
apt "org.robobinding:codegen:$robobindingVersion"
compile "org.robobinding:robobinding:$robobindingVersion:with-aop"
aspectPath("org.robobinding:robobinding:$robobindingVersion:with-aop")

compile 'org.lucasr.twowayview:twowayview:0.1.4'
compile 'com.android.support:support-v4:21.0.3'
compile 'com.android.support:recyclerview-v7:21.0.3'
provided 'com.android.support:appcompat-v7:21.0.3'
compile 'net.hockeyapp.android:HockeySDK:3.5.0-b.4'
compile 'me.dm7.barcodescanner:zbar:1.5'
compile 'com.squareup.picasso:picasso:2.4.0'
compile 'com.squareup:otto:1.3.5'

compile 'org.apache.commons:commons-lang3:3.0'

compile 'com.nispok:snackbar:2.8.0'

compile 'com.rengwuxian.materialedittext:library:1.8.0'
compile 'com.crittercism:crittercism-android-agent:+'

provided 'org.roboguice:roboblender:3.+'

compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.melnykov:floatingactionbutton:1.1.0'

compile 'com.google.code.findbugs:jsr305:1.3.9'
compile 'com.android.support:support-annotations:21.0.3'

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.0'

androidTestCompile('org.mockito:mockito-core:1.9.5',
        'com.google.dexmaker:dexmaker-mockito:1.1',
        'com.google.dexmaker:dexmaker:1.1')

}

What's strange is it work on 5.0 devices no problem.

回答1:

Older devices have problems running tests when you have the same dependency in your app and test app that instruments the app.

To work around this issue, you will have to figure out which dependencies cause the problem.

In my case it was both Dagger and Espresso depending on javax.inject and this is how it can be "fixed":

androidTestCompile('com.android.support.test.espresso:espresso-core:2.0') {
    exclude group: 'javax.inject'
}

If you include more or weirder dependencies, you may have a look at this build.gradle.

When using espresso-contrib, you may need to do this:

androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.0') {
    exclude group: 'javax.inject'
    exclude group: 'com.android.support'
}


回答2:

The problem usually happens when the same dependencies are included more than once or with different versions.

I have a working project using espresso2 with multidex for api level 14+.

Check this SO question . The accepted answer helped a lot.

Mostly, using the ./gradlew -q :myproject:dependencies you can check for duplicate dependencies or the same dependency with different versions included more than once.

This is an example of my espresso dependencies, but I had to change and exclude many:

....
//Espresso 2
androidTestCompile('com.android.support.test.espresso:espresso-core:2.0') { 
    exclude group: 'com.google.guava'
    exclude module: 'espresso-idling-resource'
}
androidTestCompile('com.android.support.test:testing-support-lib:0.1') { 
    exclude group: 'com.google.guava'
    exclude module: 'espresso-idling-resource'
}
testingCompile ('com.android.support.test.espresso:espresso-contrib:2.0') {
    exclude group: 'com.google.guava'
    exclude group: 'com.android.support', module: 'support-v4'
}
// Need to exclude this when running test
androidTestCompile('com.android.support:multidex-instrumentation:1.0.1') {
    exclude group: 'com.android.support', module: 'multidex' 
}
....

The ./gradlew -q :myproject:dependencies will give you an output like the following for every variant+flavour combination:

_prodTestingTestApk - ## Internal use, do not manually configure ##
+--- com.android.support.test.espresso:espresso-core:2.0
|    +--- com.squareup:javawriter:2.1.1
|    +--- org.hamcrest:hamcrest-integration:1.1
|    |    \--- org.hamcrest:hamcrest-core:1.1
|    +--- org.hamcrest:hamcrest-library:1.1
|    |    \--- org.hamcrest:hamcrest-core:1.1
|    +--- javax.inject:javax.inject:1
|    +--- com.android.support.test:testing-support-lib:0.1
|    |    \--- junit:junit-dep:4.10
|    |         \--- org.hamcrest:hamcrest-core:1.1
|    +--- com.google.code.findbugs:jsr305:2.0.1
|    +--- javax.annotation:javax.annotation-api:1.2
|    \--- org.hamcrest:hamcrest-core:1.1
+--- com.android.support.test:testing-support-lib:0.1 (*)
\--- com.android.support:multidex-instrumentation:1.0.1


回答3:

I had similar problem when I was operating on RecyclerView in my tests which was solved by adding below code to build.gradle:

configurations {
    androidTestCompile.exclude group: 'com.android.support', module: 'recyclerview-v7'
}

And also you can try to add following exclude as well:

configurations {
    androidTestCompile.exclude group: 'com.android.support', module: 'support-v4'
} 

So, my configurations in build.gradle looking like that:

configurations {
    androidTestCompile.exclude group: 'com.android.support', module: 'support-v4'
    androidTestCompile.exclude group: 'com.android.support', module: 'recyclerview-v7'
} 

This solved both of the issues I faced with: java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation and java.lang.NoClassDefFoundError. After that I was able to run tests on pre-lollipop devices. More here and here.