You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。
  • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:25:55