第2章 环境搭建:在Gradle中配置Robolectric依赖

说实话,环境搭建这事儿,看着简单,但坑是真的多。

我见过不少团队,代码写得挺好,一跑测试就崩。最后发现,全是配置问题。嗯,咱们这章就把Robolectric的Gradle配置理顺。把基础打好,后面才不会莫名其妙地翻车。

本章核心
完成Robolectric环境的Gradle依赖配置、SDK版本选择、测试运行器设置。
一个萝卜一个坑,配置对了,测试跑起来才顺。
环境搭建配置流程图 Robolectric 环境搭建配置流程 1. Gradle依赖配置 2. SDK版本选择 3. 测试运行器配置 4. 常见问题与兼容性 5. 验证:跑一个用例 要点 依赖版本必须匹配 注意 SDK版本不要乱改 建议 用默认TestRunner

2.1 Gradle依赖配置

第一步,打开你的 build.gradle(模块级别)

我个人习惯把测试相关的依赖单独放在 dependencies 块里。这样清晰,也好维护。

android {
    // 其他配置...
    testOptions {
        unitTests {
            includeAndroidResources = true
        }
    }
}

dependencies {
    // 核心依赖
    testImplementation "org.robolectric:robolectric:4.12.1"
    
    // 如果你用AndroidX测试库
    testImplementation "androidx.test:core:1.5.0"
    testImplementation "androidx.test:runner:1.5.2"
    
    // 可选:加个JUnit4扩展
    testImplementation "junit:junit:4.13.2"
}
小技巧
我建议把Robolectric版本号提取到项目根级别的 ext 块里。这样多模块项目统一升级,省得每个模块改一遍。

关于版本兼容性

你问Robolectric 4.12能搭配Android Gradle Plugin 8.x吗?答案是早期版本有些问题。

我曾在项目中遇到过:升级AGP到8.2后,Robolectric 4.10.1直接报 ClassNotFoundException。最后查了一圈,是SDK版本映射出了问题。升级到4.12.1就解决了。

Robolectric版本 最低AGP版本 建议Gradle版本 备注
4.9.x 7.0 7.0+ 老项目推荐
4.10.x 7.3 7.5+ 稳定
4.11.x 8.0 8.0+ 支持AGP 8.x
4.12.x 8.2 8.2+ 当前推荐

2.2 SDK版本选择

Robolectric会加载对应SDK的framework资源。说白了,你设置的SDK版本决定了测试环境的Android系统版本。

怎么配?

在 build.gradle 的 android 块里,设置默认的compileSdk、targetSdk。Robolectric会从这些值推断测试SDK版本。

android {
    compileSdk 34
    defaultConfig {
        applicationId "com.example.app"
        minSdk 21
        targetSdk 34
    }
}

但有个坑: 你设置的 compileSdk 版本,必须对应Robolectric支持的SDK镜像版本。比如Robolectric 4.12.1内置了SDK 21到SDK 34的镜像。如果compileSdk设为35,测试时会去下载镜像——下载失败就直接挂。

⚡ 避坑指南
我曾经在项目里把 compileSdk 改成35,结果Robolectric跑不起来。后来发现官方还没发布35的镜像。所以,我建议保持 compileSdk 不超过Robolectric包内置的最高版本。

2.3 测试运行器配置

默认情况下,Robolectric会使用内置的 androidx.test.runner.AndroidJUnitRunner。但你要告诉Gradle,单元测试走Robolectric,而不是真机或模拟器。

配置方式有两种:

  1. 在 build.gradle 中设置
    在每个模块的 android.defaultConfig 或 android.testOptions 里指定:
    android {
        defaultConfig {
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
    }
    实际上,Robolectric不需要显式替换运行器。它的原理是通过 includeAndroidResources = true 和依赖库自动注入Shadow类。你只要确保 testOptions 开启了Android资源支持。
  2. 自定义TestRunner
    如果你需要定制Robolectric的行为,可以建一个自定义Runner:
    import org.junit.runners.model.InitializationError
    import org.robolectric.RobolectricTestRunner
    
    class CustomRobolectricRunner : RobolectricTestRunner {
        constructor(klass: Class<*>) : super(klass) {
            // 可以在这里配置SDK版本、应用包名等
        }
    }
    然后在测试类上用 @RunWith(CustomRobolectricRunner::class)。
我的经验
大部分项目不需要自定义Runner。直接用默认的即可。除非你遇到特殊的SDK版本冲突或需要全局覆盖某些配置。

2.4 验证:第一个能跑的测试

配置完成后,写一个最简单的测试来验证环境是否正常:

import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.junit.Assert.*

@RunWith(RobolectricTestRunner::class)
class EnvironmentCheckTest {

    @Test
    fun testSdkVersion() {
        val sdk = RuntimeEnvironment.getApiLevel()
        println("当前测试SDK版本: $sdk")
        assertNotNull(sdk)
    }
}

右键运行这个测试。如果绿色通过,说明环境搭建成功。

常见失败原因:

  • ClassNotFoundException: Robolectric依赖没加上或版本冲突。
  • NoSuchMethodError: Robolectric版本和Android Gradle Plugin不匹配。
  • SDK镜像下载失败: 检查网络,或在 settings.gradle 中添加阿里云镜像。
网络依赖问题
如果你们团队在离线内网开发,需要提前下载好Robolectric的SDK镜像文件,放到 ~/.m2/repository 目录下。否则第一次运行会卡在下载镜像上。