NoClassDefFoundError while running unit tests with

2019-06-18 14:27发布

问题:

My Android project has several modules (one application and multiple libraries) and when I try to run all the unit tests (Robolectric 3.8) from the command line

./gradlew testDebugUnitTest

I get the following error (not when I run the same task from Android Studio)

java.lang.NoClassDefFoundError: android/content/Context at java.base/java.lang.Class.getDeclaredConstructors0(Native Method) at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3110) at java.base/java.lang.Class.getConstructor0(Class.java:3315) at java.base/java.lang.Class.getConstructor(Class.java:2108) at org.robolectric.RobolectricTestRunner.getHooksInterface(RobolectricTestRunner.java:473) at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:308) at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:241) at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:123) at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:42) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:77) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy1.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:108) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) at java.base/java.lang.Thread.run(Thread.java:844) Caused by: java.lang.ClassNotFoundException: couldn't load android.content.Context at org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:174) at org.robolectric.internal.bytecode.SandboxClassLoader.lambda$findClass$0(SandboxClassLoader.java:133) at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:50) at org.robolectric.internal.bytecode.SandboxClassLoader.findClass(SandboxClassLoader.java:132) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:563) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496) ... 45 more Caused by: java.lang.IllegalArgumentException at org.objectweb.asm.ClassReader.(Unknown Source) at org.objectweb.asm.ClassReader.(Unknown Source) at org.robolectric.internal.bytecode.SandboxClassLoader$ClassInstrumentor.isOverridingFinalMethod(SandboxClassLoader.java:502) at org.robolectric.internal.bytecode.SandboxClassLoader$ClassInstrumentor.instrumentInheritedObjectMethod(SandboxClassLoader.java:523) at org.robolectric.internal.bytecode.SandboxClassLoader$ClassInstrumentor.instrument(SandboxClassLoader.java:395) at org.robolectric.internal.bytecode.SandboxClassLoader$InvokeDynamicClassInstrumentor.instrument(SandboxClassLoader.java:1274) at org.robolectric.internal.bytecode.SandboxClassLoader.getInstrumentedBytes(SandboxClassLoader.java:271) at org.robolectric.internal.bytecode.SandboxClassLoader.lambda$maybeInstrumentClass$1(SandboxClassLoader.java:166) at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:50) at org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:165) ... 50 more

The build.gradle file on each module contains the following configuration

testOptions {
    unitTests {
        returnDefaultValues true
    }
}

The application module defines a couple of flavours all running in the same dimension

flavorDimensions 'default'

Any idea?

回答1:

I have that kind of (not same)error before. I think NoClassDefFoundError is telling you that your Android application is running on a different version of android like 32bit or 64 bit you need to add jniLibs folder in the android project.

That get your library according to a device at runtime.

Search about JniLibs about more.

Thanks!!



回答2:

It has to be with your dependencies. You have to put the dependencies you use with testImplementation.

For example, I was getting the error having this dependency defined:

compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.2"

Now I've added the other one:

//Used to compile
compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.2"
//Used to compile tests
testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.2"

Check what dependency you are missing running

./gradlew test --stacktrace

Gradle will automatically generate html with all the trace organized.

It's just a possibility, let me know if it works.

UPDATE: This work only if you use compileOnly with the missed dependencies. The reason is that compileOnly declares dependencies only used at compilation time, so we need testImplementation also. Another solution would be to directly use implementation which would add the requires dependencies (so we wouldn't need testImplementation).