dagger-instrumentation-example
dagger-instrumentation-example copied to clipboard
ClassNotFoundException on KitKat
When I run connectedAndroidTest
on either a emulator or physical device running 4.4, the tests fail due to a ClassNotFoundException
. However, when I run connectedAndroidTest
against an emulator running Lollipop, the tests work as expected and are successful.
Have you had success running the tests on a KitKat device or emulator?
Other details:
- Emulator is running the x86 image
- KitKat device is running the Dalvik runtime
- Running the tests with the gradle wrapper.
- Android Studio v1.0.2
Here is the output from the failing tests.
Tests on Nexus_5_API_19(AVD) - 4.4.2 failed: Instrumentation run failed due to 'java.lang.ClassNotFoundException'
com.android.builder.testing.ConnectedDevice > hasTests[Nexus_5_API_19(AVD) - 4.4.2] FAILED
No tests found.
Tests on XT1060 - 4.4.4 failed: Instrumentation run failed due to 'java.lang.ClassNotFoundException'
com.android.builder.testing.ConnectedDevice > hasTests[XT1060 - 4.4.4] FAILED
No tests found.
:app:connectedAndroidTest FAILED
FAILURE: Build failed with an exception.
This was working on KitKat a few weeks ago, but now there seems to be a run-time issue when initializing the dependency graphs during the instrumentation tests. I have no problems building and running the app on KitKat. I'll try digging into this more, but the issue not obvious to me.
Here is the logcat output when the tests are being run against a 4.4 emulator.
I/MonitoringInstrumentation( 2494): Instrumentation Started!
W/dalvikvm( 2494): Class resolved by unexpected DEX: Ldagger/Factory;(0xb1033190):0xab5b8000 ref [Ljavax/inject/Provider;] Ljavax/inject/Provider;(0xb1033190):0xab612000
W/dalvikvm( 2494): (Ldagger/Factory; had used a different Ljavax/inject/Provider; during pre-verification)
I/dalvikvm( 2494): Failed resolving Ldagger/Factory; interface 2164 'Ljavax/inject/Provider;'
W/dalvikvm( 2494): Link of class 'Ldagger/Factory;' failed
I/dalvikvm( 2494): Failed resolving Lcom/circle/testexample/data/DebugDataModule$$ProvideApiFactory; interface 1921 'Ldagger/Factory;'
W/dalvikvm( 2494): Link of class 'Lcom/circle/testexample/data/DebugDataModule$$ProvideApiFactory;' failed
D/AndroidRuntime( 2494): Shutting down VM
W/dalvikvm( 2494): threadid=1: thread exiting with uncaught exception (group=0xb0d2ab20)
E/MonitoringInstrumentation( 2494): Exception encountered by: Thread[main,5,main]. Dumping thread state to outputs and pining for the fjords.
E/MonitoringInstrumentation( 2494): java.lang.NoClassDefFoundError: com/circle/testexample/data/DebugDataModule$$ProvideApiFactory
E/MonitoringInstrumentation( 2494): at com.circle.testexample.Dagger_Graph.initialize(Dagger_Graph.java:50)
E/MonitoringInstrumentation( 2494): at com.circle.testexample.Dagger_Graph.<init>(Dagger_Graph.java:42)
E/MonitoringInstrumentation( 2494): at com.circle.testexample.Dagger_Graph.<init>(Dagger_Graph.java:24)
E/MonitoringInstrumentation( 2494): at com.circle.testexample.Dagger_Graph$Builder.build(Dagger_Graph.java:84)
E/MonitoringInstrumentation( 2494): at com.circle.testexample.Graph$Initializer.init(Graph.java:19)
E/MonitoringInstrumentation( 2494): at com.circle.testexample.App.onCreate(App.java:15)
E/MonitoringInstrumentation( 2494): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)
E/MonitoringInstrumentation( 2494): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4344)
E/MonitoringInstrumentation( 2494): at android.app.ActivityThread.access$1500(ActivityThread.java:135)
E/MonitoringInstrumentation( 2494): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
E/MonitoringInstrumentation( 2494): at android.os.Handler.dispatchMessage(Handler.java:102)
E/MonitoringInstrumentation( 2494): at android.os.Looper.loop(Looper.java:136)
E/MonitoringInstrumentation( 2494): at android.app.ActivityThread.main(ActivityThread.java:5017)
E/MonitoringInstrumentation( 2494): at java.lang.reflect.Method.invokeNative(Native Method)
E/MonitoringInstrumentation( 2494): at java.lang.reflect.Method.invoke(Method.java:515)
E/MonitoringInstrumentation( 2494): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
E/MonitoringInstrumentation( 2494): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
E/MonitoringInstrumentation( 2494): at dalvik.system.NativeStart.main(Native Method)
E/MonitoringInstrumentation( 2494): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.circle.testexample.data.DebugDataModule$$ProvideApiFactory" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/data/app/com.circle.testexample.test-1.apk", zip file "/data/app/com.circle.testexample-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.circle.testexample.test-1, /data/app-lib/com.circle.testexample-1, /vendor/lib, /system/lib]]
E/MonitoringInstrumentation( 2494): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
E/MonitoringInstrumentation( 2494): at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
E/MonitoringInstrumentation( 2494): at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
E/MonitoringInstrumentation( 2494): ... 18 more
To get past the NoClassDefFoundError
for the generated dagger classes, I had to exclude the javax.inject
group from the espresso 2.0 dependency.
androidTestCompile ('com.android.support.test.espresso:espresso-core:2.0') {
exclude group: 'javax.inject'
}
However, I am still stuck with the following NoClassDefFoundError
when running the tests.
com.circle.testexample.MainActivityTest > testLoginFailure[SM-P600 - 4.4.2] [31mFAILED [0m
java.lang.NoClassDefFoundError: org/mockito/internal/matchers/Equals
at org.mockito.internal.invocation.ArgumentsProcessor.argumentsToMatchers(ArgumentsProcessor.java:47)
com.circle.testexample.MainActivityTest > testLoginSuccess[SM-P600 - 4.4.2] [31mFAILED [0m
java.lang.NoClassDefFoundError: org/mockito/internal/matchers/Equals
at org.mockito.internal.invocation.ArgumentsProcessor.argumentsToMatchers(ArgumentsProcessor.java:47)
:app:connectedAndroidTest FAILED
FAILURE: Build failed with an exception.
I've been working the exact same setup on and off for the past few days. I'm hoping we can get this figured out.
Nice find. I'll take a look tonight, but I'm guessing that second issue is the Hamcrest dependency used in both projects.
I think you have the right idea about their being a conflict with the Hamcrest dependency.
01-12 12:06:09.834 30378-30391/com.circle.testexample W/dalvikvm﹕ Class resolved by unexpected DEX: Lorg/mockito/ArgumentMatcher;(0x421d8b58):0x78cb0000 ref [Lorg/hamcrest/BaseMatcher;] Lorg/hamcrest/BaseMatcher;(0x421d8b58):0x78855000
01-12 12:06:09.834 30378-30391/com.circle.testexample W/dalvikvm﹕ (Lorg/mockito/ArgumentMatcher; had used a different Lorg/hamcrest/BaseMatcher; during pre-verification)
01-12 12:06:09.834 30378-30391/com.circle.testexample W/dalvikvm﹕ Unable to resolve superclass of Lorg/mockito/ArgumentMatcher; (2185)
01-12 12:06:09.834 30378-30391/com.circle.testexample W/dalvikvm﹕ Link of class 'Lorg/mockito/ArgumentMatcher;' failed
01-12 12:06:09.834 30378-30391/com.circle.testexample W/dalvikvm﹕ Unable to resolve superclass of Lorg/mockito/internal/matchers/Equals; (2224)
01-12 12:06:09.839 30378-30391/com.circle.testexample W/dalvikvm﹕ Link of class 'Lorg/mockito/internal/matchers/Equals;' failed
01-12 12:06:09.839 30378-30391/com.circle.testexample I/TestRunner﹕ failed: testLoginSuccess(com.circle.testexample.MainActivityTest)
I found a fix, but I'm not crazy about it. Including Espresso as a debug dependency instead of as a android test dependency solves the issue. I'm not sure why this works.
debugCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
debugCompile 'com.google.dexmaker:dexmaker:1.0'
debugCompile 'org.mockito:mockito-core:1.10.17'
debugCompile ('com.android.support.test.espresso:espresso-core:2.0') {
exclude group: 'javax.inject'
}
debugCompile 'com.android.support.test:testing-support-lib:0.1'
I ran across that as well and didn't really like it. Just to document another bad solution:
androidTestProvided 'com.android.support.test:testing-support-lib:0.1'
androidTestProvided ('com.android.support.test.espresso:espresso-core:2.0') {
exclude group: 'javax.inject'
}
// adds the @Generated annoation that Android lacks
debugCompile ('com.google.dexmaker:dexmaker-mockito:1.0') {
exclude group: 'org.hamcrest'
}
debugCompile ('com.google.dexmaker:dexmaker:1.0') {
exclude group: 'org.hamcrest'
}
debugCompile ('org.mockito:mockito-core:1.10.17') {
exclude group: 'org.hamcrest'
}
Using the above configuration will result in the tests passing and the debug build running on the device just fine. It appears when Hamcrest is pulled in by testing-support-lib
in the andoridTest
build, the Hamcrest dependency in the debug
build will be satisfied too.
The bad part is if you try to access anything within Hamcrest when you run just the debug
build on the device it will crash with a NoClassDefFoundError
. For example, if you add when(api.login(anyString(), anyString())).thenReturn(Observable.just(false));
before the Mocked Api
in DebugDataModule
is returned the app will crash.
I'm beginning to wonder if this is just a limitation of the build system. I'm not quite sure but we may be running into https://code.google.com/p/android/issues/detail?id=65445.
Ran into the same problem trying to port u2020-mvp tests to Espresso 2 and JUnit4. Since I am not using Mockito this helped me:
androidTestCompile ('com.android.support.test.espresso:espresso-core:2.0') {
exclude group: 'javax.inject'
}
However, source of the problem is still undefined for me.
I think the source of the problem above, is about this bug: https://code.google.com/p/android/issues/detail?id=65445
I solved similar exceptions with the following build config ( I am using debugTest for my test specific class, i.e. modules)
debugTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
debugTestCompile 'com.google.dexmaker:dexmaker:1.0'
debugTestCompile 'org.mockito:mockito-core:1.10.17'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
androidTestCompile 'com.google.dexmaker:dexmaker:1.0'
androidTestCompile 'org.mockito:mockito-core:1.10.17'
// Mock web server
debugTestCompile('com.squareup.okhttp:mockwebserver:2.2.0') {
exclude group: 'com.squareup.okhttp'
}
//Espresso
androidTestCompile ('com.android.support.test.espresso:espresso-core:2.0'){
exclude group:'javax.inject'
}
androidTestCompile ('com.android.support.test:testing-support-lib:0.1'){
}
However both in my own project and this example project, I am currently getting the following error:
Note: Generating a MembersInjector or Factory for com.circle.testexample.InjectedBaseActivityTest. Prefer to run the dagger processor over that class instead.
C:\Development\Projects\dagger-instrumentation-example\app\src\debug\java\com\circle\testexample\InjectedBaseActivityTest.java:10: error: Could not generate [com.circle.testexample.InjectedBaseActivityTest$$MembersInjector]: Attempt to recreate a file for type com.circle.testexample.InjectedBaseActivityTest$$MembersInjector.
public class InjectedBaseActivityTest<T extends BaseActivity> extends ActivityInstrumentationTestCase2<T> {
^
1 error
I couldn't find any solution to this so far, or any other way to inject the test classes for that matter. Any ideas?
@emredirican, I think that error has something to do with the latest changes to Dagger 2. Other projects that I'm using this method in suddenly stopped building today with that same error.
@bryanstern Indeed, I realized that the error showed up after updating Dagger 2 snapshot. I will take a look again tomorrow. Let me know if you find a solution in the mean time.
I was able to work around the Generating a MembersInjector or Factory...
error by pulling the injected fields out into a base class, and leaving the generics in the subclass.
I'm going to clean this up once 1.1 of the Android Gradle Plugin is released. Looks like that version will fix these dependency issues. https://code.google.com/p/android/issues/detail?id=65445