使用 Roboelectric 3.8 运行单元测试时出现 NoClassDefFoundError
Posted
技术标签:
【中文标题】使用 Roboelectric 3.8 运行单元测试时出现 NoClassDefFoundError【英文标题】:NoClassDefFoundError while running unit tests with Roboelectric 3.8 【发布时间】:2018-12-01 18:58:53 【问题描述】:我的 android 项目有多个模块(一个应用程序和多个库),当我尝试从命令行运行所有单元测试 (Robolectric 3.8) 时
./gradlew testDebugUnitTest
我收到以下错误(不是当我从 Android Studio 运行相同任务时)
java.lang.NoClassDefFoundError: android/content/Context at java.base/java.lang.Class.getDeclaredConstructors0(Native Method) 在 java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3110) 在 java.base/java.lang.Class.getConstructor0(Class.java:3315) 在 java.base/java.lang.Class.getConstructor(Class.java:2108) 在 org.robolectric.RobolectricTestRunner.getHooksInterface(RobolectricTestRunner.java:473) 在 org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:308) 在 org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:241) 在 org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:123) 在 org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:42) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 在 org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:77) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在 org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114) 在 org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) 在 org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) 在 org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) 在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native 方法)在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.base/java.lang.reflect.Method.invoke(Method.java:564) 在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) 在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) 在 org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) 在 org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) 在 com.sun.proxy.$Proxy1.processTestClass(Unknown Source) 在 org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:108) 在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native 方法)在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.base/java.lang.reflect.Method.invoke(Method.java:564) 在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) 在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) 在 org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146) 在 org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128) 在 org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) 在 org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) 在 org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) 在 java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 在 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 在 org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) 在 java.base/java.lang.Thread.run(Thread.java:844) 引起: java.lang.ClassNotFoundException:无法加载 android.content.Context 在 org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:174) 在 org.robolectric.internal.bytecode.SandboxClassLoader.lambda$findClass$0(SandboxClassLoader.java:133) 在 org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:50) 在 org.robolectric.internal.bytecode.SandboxClassLoader.findClass(SandboxClassLoader.java:132) 在 java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:563) 在 java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496) ... 45 更多原因: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) 在 org.robolectric.internal.bytecode.SandboxClassLoader$ClassInstrumentor.instrumentInheritedObjectMethod(SandboxClassLoader.java:523) 在 org.robolectric.internal.bytecode.SandboxClassLoader$ClassInstrumentor.instrument(SandboxClassLoader.java:395) 在 org.robolectric.internal.bytecode.SandboxClassLoader$InvokeDynamicClassInstrumentor.instrument(SandboxClassLoader.java:1274) 在 org.robolectric.internal.bytecode.SandboxClassLoader.getInstrumentedBytes(SandboxClassLoader.java:271) 在 org.robolectric.internal.bytecode.SandboxClassLoader.lambda$maybeInstrumentClass$1(SandboxClassLoader.java:166) 在 org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:50) 在 org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:165) ... 50 更多
每个模块上的 build.gradle 文件包含以下配置
testOptions
unitTests
returnDefaultValues true
应用模块定义了几个flavor都在同一个维度上运行
flavorDimensions 'default'
有什么想法吗?
【问题讨论】:
你试过在另一台机器上运行它吗?在我的情况下,错误的测试数量各不相同,是什么让我认为它必须与使用的某些特定版本有关...... 【参考方案1】:我以前有过那种(不一样的)错误。我认为 NoClassDefFoundError 是在告诉您,您的 Android 应用程序在不同版本的 android 上运行,例如 32 位或 64 位,您需要在 android 项目中添加 jniLibs 文件夹。 p>
在运行时根据设备获取你的库。
搜索有关 JniLibs 的更多信息。
谢谢!!
【讨论】:
谢谢@jigar-fumakiya,您能帮我了解如何将您的解决方案应用于我的问题吗?我的测试在 Java 代码上运行,我没有任何库可以在 jniLibs 路径中列出。【参考方案2】:它必须与您的依赖项有关。您必须将您使用的依赖项与testImplementation
.
例如,我在定义此依赖项时遇到错误:
compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.2"
现在我添加了另一个:
//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"
检查你在运行时缺少什么依赖项
./gradlew test --stacktrace
Gradle 将自动生成 html,并组织所有跟踪。
这只是一种可能,如果可行,请告诉我。
更新:仅当您将compileOnly
与缺少的依赖项一起使用时才有效。原因是compileOnly
声明了仅在编译时使用的依赖项,所以我们还需要testImplementation
。另一种解决方案是直接使用implementation
,这将添加所需的依赖项(因此我们不需要testImplementation
)。
【讨论】:
以上是关于使用 Roboelectric 3.8 运行单元测试时出现 NoClassDefFoundError的主要内容,如果未能解决你的问题,请参考以下文章