Robolectric多Dex测试初始化报错及替代方案咨询
问题描述
我尝试使用Robolectric运行Android单元测试,以便在多Dex应用中访问Context。以下是我的build.gradle依赖配置:
implementation 'androidx.test.ext:junit:1.1.5' testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:3.2.0' testImplementation 'org.robolectric:robolectric:4.9' testImplementation "org.robolectric:shadows-multidex:3.0" testImplementation 'androidx.test:core:1.5.0'
运行测试时初始化阶段出现如下错误:
Receiver class org.robolectric.shadows.multidex.Shadows does not define or inherit an implementation of the resolved method 'abstract java.util.Collection getShadows()' of interface org.robolectric.internal.ShadowProvider. java.lang.AbstractMethodError: Receiver class org.robolectric.shadows.multidex.Shadows does not define or inherit an implementation of the resolved method 'abstract java.util.Collection getShadows()' of interface org.robolectric.internal.ShadowProvider. at org.robolectric.internal.bytecode.ShadowMap.createFromShadowProviders(ShadowMap.java:42) at org.robolectric.internal.bytecode.ShadowProviders.<init>(ShadowProviders.java:28) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) at org.robolectric.util.inject.Injector.inject(Injector.java:250) at org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:232) at org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:498) at org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:224) at org.robolectric.util.inject.Injector.getInstance(Injector.java:208) at org.robolectric.util.inject.Injector.getInstance(Injector.java:202) at org.robolectric.internal.SandboxTestRunner.<init>(SandboxTestRunner.java:79) at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:106) at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:101) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104) at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70) at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70) at org.junit.internal.requests.ClassRequest.createRunner(ClassRequest.java:28) at org.junit.internal.requests.MemoizingRequest.getRunner(MemoizingRequest.java:19) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:78) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62) 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:566) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94) at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176) at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60) at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71) at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69) at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
同时想咨询:现在是否仍需使用Robolectric?AndroidX是否已支持Context的测试?
解决方案
1. 修复版本不兼容问题
你遇到的AbstractMethodError是因为Robolectric主库版本(4.9)和shadows-multidex版本(3.0)不匹配。Robolectric 4.x系列的API发生了变化,旧版本的shadows-multidex没有实现新的getShadows()方法。
两种修复方式:
- 升级
shadows-multidex版本,与Robolectric主库保持一致:testImplementation "org.robolectric:shadows-multidex:4.9" - 从Robolectric 4.3开始,多Dex支持已集成到主库中,可直接移除
shadows-multidex依赖,无需单独引入。
2. Robolectric必要性与AndroidX测试支持说明
是否仍需Robolectric?
取决于测试场景:- 若需要在本地JVM中运行依赖Android框架的单元测试(比如访问真实
Context、测试资源加载、四大组件逻辑等),Robolectric仍是首选方案之一,它提供完整的Android框架模拟,测试速度远快于仪器化测试。 - 若测试仅涉及纯Java逻辑,无Android框架依赖,则无需使用Robolectric。
- 若需要在本地JVM中运行依赖Android框架的单元测试(比如访问真实
AndroidX是否支持Context测试?
AndroidX Test提供了仪器化测试(在真机/模拟器运行)来访问真实Context,比如通过ApplicationProvider.getApplicationContext()获取应用上下文,但这类测试运行速度较慢。若想在本地单元测试中结合AndroidX API获取Context,可搭配Robolectric使用,示例代码:
@RunWith(RobolectricTestRunner.class) public class ExampleTest { @Test public void testContext() { Context context = ApplicationProvider.getApplicationContext(); // 测试逻辑 } }
内容的提问来源于stack exchange,提问作者Ginger McMurray
相关产品推荐
相关产品推荐

