Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tests fail after Espresso 2 upgrade (failed: Instrumentation run failed due to 'java.lang.IllegalAccessError')

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.

like image 726
Graeme Avatar asked Feb 16 '15 23:02

Graeme


3 Answers

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'
}
like image 89
MaciejGórski Avatar answered Nov 13 '22 01:11

MaciejGórski


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
like image 25
marbarfa Avatar answered Nov 13 '22 01:11

marbarfa


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.

like image 5
denys Avatar answered Nov 13 '22 00:11

denys