在 Android 中搭建 单元测试(Unit Test) 环境,主要涉及 JUnit、Mockito、Robolectric 等工具。本文介绍如何搭建完整的单元测试环境,并配置 Gradle、测试规则、Mock 依赖 等,确保代码可以高效测试。
1. 配置 Gradle
(1)添加依赖
在 build.gradle.kts
(模块级)中添加单元测试相关依赖:
scss
dependencies {
// JUnit 5 单元测试框架
testImplementation("org.junit.jupiter:junit-jupiter:5.9.3")
// Mockito 用于 Mock 依赖
testImplementation("org.mockito:mockito-core:5.7.0")
testImplementation("org.mockito:mockito-inline:5.2.0")
// Kotlin 扩展版 Mockito
testImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0")
// Robolectric 模拟 Android 组件环境
testImplementation("org.robolectric:robolectric:4.11.1")
// 用于测试 Kotlin 协程
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1")
// 断言库(更优雅的断言)
testImplementation("org.assertj:assertj-core:3.24.2")
// JSON 解析辅助(用于 Mock API)
testImplementation("com.google.code.gson:gson:2.10.1")
}
✅ JUnit 5 作为核心测试框架
✅ Mockito 让你可以 Mock 依赖,隔离测试对象
✅ Robolectric 在 JVM 上运行 Android 组件 ,避免依赖真机
✅ Coroutines Test 让 协程测试更稳定
(2)启用 JUnit 5
在 gradle.properties
中启用 JUnit 5:
ini
android.testOptions.unitTests.includeAndroidResources=true
JUnit 4 vs. JUnit 5?
- JUnit 5(推荐) :支持更多注解、嵌套测试、动态测试
- JUnit 4:老项目兼容性更好,但不如 JUnit 5 强大
2. 目录结构
单元测试文件放在:
scss
app/src/test/java/com/example/app/ // 运行在 JVM,适合单元测试
app/src/androidTest/java/com/example/app/ // 运行在 Android 设备,适合 UI 测试
test/
:用于单元测试(Mockito、JUnit、Robolectric)androidTest/
:用于 UI 测试(Espresso、UI Automator)
3. 编写单元测试
(1)测试普通类
示例:测试 Calculator
类
kotlin
class Calculator {
fun add(a: Int, b: Int) = a + b
}
测试 CalculatorTest
:
kotlin
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class CalculatorTest {
private val calculator = Calculator()
@Test
fun `test addition`() {
val result = calculator.add(3, 5)
assertEquals(8, result)
}
}
✅ JUnit 5 语法 ,更清晰的 assertEquals
断言
(2)Mock 依赖
测试 UserRepository
:
kotlin
class UserRepository(private val apiService: ApiService) {
suspend fun getUser(): User {
return apiService.getUser()
}
}
使用 Mockito
Mock ApiService
:
kotlin
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import kotlin.test.assertEquals
class UserRepositoryTest {
@Mock
lateinit var apiService: ApiService
private lateinit var userRepository: UserRepository
@BeforeEach
fun setUp() {
MockitoAnnotations.openMocks(this)
userRepository = UserRepository(apiService)
}
@Test
fun `get user data successfully`() = runBlocking {
val mockUser = User("John", 25)
`when`(apiService.getUser()).thenReturn(mockUser)
val result = userRepository.getUser()
assertEquals(mockUser, result)
}
}
✅ Mock ApiService
,避免真实网络请求
✅ 使用 runBlocking
处理 suspend
函数
(3)Robolectric 测试 Android 组件
测试 SharedPreferences
:
kotlin
import android.content.Context
import android.content.SharedPreferences
import androidx.test.core.app.ApplicationProvider
import org.junit.Assert.assertEquals
import org.junit.Test
import org.robolectric.RobolectricTestRunner
import org.junit.runner.RunWith
@RunWith(RobolectricTestRunner::class)
class SharedPreferencesTest {
private val context = ApplicationProvider.getApplicationContext<Context>()
private val sharedPreferences: SharedPreferences = context.getSharedPreferences("test_prefs", Context.MODE_PRIVATE)
@Test
fun `save and retrieve data`() {
sharedPreferences.edit().putString("key", "value").apply()
assertEquals("value", sharedPreferences.getString("key", null))
}
}
✅ Robolectric 让 SharedPreferences 运行在 JVM 上,无需 Android 设备
4. Mock API
使用 MockWebServer
测试 API
kotlin
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
class ApiServiceTest {
private lateinit var mockWebServer: MockWebServer
@Before
fun setup() {
mockWebServer = MockWebServer()
mockWebServer.start()
}
@After
fun teardown() {
mockWebServer.shutdown()
}
@Test
fun `test API response`() {
mockWebServer.enqueue(MockResponse().setBody("{"name":"John"}"))
val result = apiService.getUser()
assertEquals("John", result.name)
}
}
✅ 隔离网络请求,确保 API 逻辑可靠
5. 运行测试
(1)运行所有单元测试
bash
./gradlew test
(2)运行指定测试
bash
./gradlew testDebugUnitTest --tests "com.example.app.UserRepositoryTest"
(3)生成测试覆盖率报告
bash
./gradlew jacocoTestReport
JaCoCo 可以生成代码覆盖率报告,帮助检查哪些代码缺少测试。
总结
目标 | 方案 |
---|---|
核心测试框架 | JUnit 5 |
Mock 依赖 | Mockito |
模拟 Android 组件 | Robolectric |
测试 API | MockWebServer |
异步测试 | Coroutines Test |
自动化运行 | Gradle ./gradlew test |
你现在可以在 Android 项目中高效执行单元测试!如果你的项目有特殊需求(比如 RxJava、LiveData ),可以继续优化测试方案。🚀