项目初始化与依赖:Gradle 配置、Compose 版本、测试库

本章要点

  • 理解 State Hoisting 测试夹具分离对项目结构的影响
  • 正确配置 Gradle 多模块项目,添加 Compose 核心依赖
  • 指定 Compose BOM 版本与 Kotlin 编译器版本
  • 为夹具模块添加测试专用库(JUnit、Compose UI Test)
  • 规避版本不对齐导致的编译/运行时异常

项目结构概述

测试夹具分离要求将测试辅助代码(自定义布局、验证函数、模拟状态等)放在独立的模块中,实现编译期隔离与复用。典型工程结构如下:

MyComposeApp/
├── settings.gradle.kts
├── app/                      # 主应用模块
│   └── build.gradle.kts
├── shared-test/              # 测试夹具模块(分离后新增)
│   └── build.gradle.kts
└── lib/                      # 业务/Compose 组件模块(可选)
    └── build.gradle.kts

Gradle 配置详解

1. 根 settings.gradle.kts

声明所有模块,并启用统一依赖版本管理。

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "MyComposeApp"
include(":app")
include(":shared-test")
include(":lib")

2. 主应用模块 app/build.gradle.kts

使用 Compose BOM 统一版本,声明核心 UI 依赖,并引用测试夹具模块。

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.example.app"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.app"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"
    }

    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.8"
    }
}

dependencies {
    // Compose BOM
    val composeBom = platform("androidx.compose:compose-bom:2024.02.00")
    implementation(composeBom)
    androidTestImplementation(composeBom)

    // Compose 核心
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.material3:material3")
    implementation("androidx.compose.ui:ui-tooling-preview")
    debugImplementation("androidx.compose.ui:ui-tooling")

    // 依赖测试夹具模块
    testImplementation(project(":shared-test"))
    androidTestImplementation(project(":shared-test"))

    // AndroidX 测试
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    androidTestImplementation("androidx.compose.ui:ui-test-junit4")
    debugImplementation("androidx.compose.ui:ui-test-manifest")
}

3. 测试夹具模块 shared-test/build.gradle.kts

该模块专为测试夹具而生,不包含业务代码,仅暴露可复用的测试辅助类。

plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.example.sharedtest"
    compileSdk = 34

    defaultConfig {
        minSdk = 24
    }

    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.8"
    }
}

dependencies {
    // 只需 Compose UI 和测试库,不依赖主应用
    val composeBom = platform("androidx.compose:compose-bom:2024.02.00")
    implementation(composeBom)

    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-test-junit4")   // 夹具中需使用测试 API
    implementation("androidx.compose.ui:ui-test-manifest")

    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
}

Compose 版本与测试库版本对照

版本不匹配是常见错误根源,下表列出推荐组合:

Compose BOM 版本 Kotlin 版本 kotlinCompilerExtensionVersion ui-test-junit4 版本 ui-test-manifest 版本
2024.02.00 1.9.22 1.5.8 随 BOM (1.6.2) 随 BOM (1.6.2)
2024.01.00 1.9.21 1.5.7 随 BOM (1.6.1) 随 BOM (1.6.1)
2023.10.01 1.9.20 1.5.5 随 BOM (1.5.5) 随 BOM (1.5.5)
版本对齐最佳实践
使用 platform("androidx.compose:compose-bom:…") 作为 BOM 依赖,无需逐一指定 Compose 子库版本。但 kotlinCompilerExtensionVersion 必须与 Kotlin 主版本严格一致,否则会报 Unsupported Kotlin version 错误。

常见错误与调试

  • 编译器版本不匹配:kotlinCompilerExtensionVersion 对应的 Kotlin 版本与项目中 kotlin-gradle-plugin 版本不一致。解决方案:查阅 官方对应表。
  • 夹具模块访问不到 ui-test-junit4:确保在 shared-test 模块中 implementation 而非 androidTestImplementation,因为夹具代码是被主模块的 test 和 androidTest 共同使用的。
  • 测试时找不到夹具类:检查 testImplementation(project(":shared-test")) 和 androidTestImplementation(project(":shared-test")) 是否同时添加。
  • 编译时重复类定义:夹具模块不要依赖 app 模块,避免循环引用;共享的测试辅助类应只声明一次。

构建验证命令

完成配置后执行以下命令验证依赖解析与编译:

./gradlew :shared-test:assembleDebug
./gradlew :app:assembleDebug
./gradlew :app:testDebugUnitTest
./gradlew :app:connectedDebugAndroidTest
注意:调试依赖的作用域
debugImplementation("androidx.compose.ui:ui-test-manifest") 只在 debug 构建时生效,用于支持 Compose 测试工具(如 createComposeRule)。如果漏掉此依赖,androidTest 时可能抛出 Missing activity 异常。

项目依赖结构图

项目初始化的模块依赖关系(State Hoisting 测试夹具分离) app(主模块) Compose UI / 业务逻辑 shared-test(夹具模块) 测试辅助类 / 封装验证 lib(公共组件) 可复用的 Compose 组件 AndroidX Compose UI / Material3 / Test JUnit + Test Runner 单元 / 集成测试框架 testImplementation / androidTestImplementation implementation BOM 统一版本 implementation (ui-test-junit4) test / androidTest 🚀 分离后的 shared-test 模块可被 app 和 lib 同时复用,避免重复编写测试夹具代码

优化建议

  • 统一 BOM 版本:所有模块使用同一个 BOM 变量(可在根 build.gradle.kts 或 libs.versions.toml 中声明),避免碎片化。
  • 精简夹具模块依赖:只保留 ui-test-junit4 和 ui-test-manifest,不要引入 Material3 等业务依赖,避免测试环境和生产环境耦合。
  • 利用 debugImplementation:将 ui-tooling 和 ui-test-manifest 放在 debugImplementation 作用域下,release 构建时自动排除,缩小 APK 体积。