Android 单元测试环境搭建

在 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 依赖,隔离测试对象

RobolectricJVM 上运行 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 ),可以继续优化测试方案。🚀

相关推荐
sdkdlwk4 小时前
Android_P_Audio_系统(1) — Auido 系统简介
android·audio
XJSFDX_Ali6 小时前
安卓开发,打开PDF文件
android·java·开发语言·pdf
Snow_Dragon_L6 小时前
【MySQL】语言连接
android·数据库·后端·sql·mysql·ubuntu·adb
m0_7482329210 小时前
mysql-connector-java 和 mysql-connector-j的区别
android·java·mysql
今人不见古时月,今月曾经照古人11 小时前
android 自定义通话录音
android
简知圈11 小时前
【01-Qt-C++-android】
android·c++·qt
OCR_API11 小时前
实名制-网络平台集成身份证实名认证接口/身份证查询-PHP
android·开发语言·php
工程师老罗12 小时前
我用Ai学Android Jetpack Compose之CircularProgressIndicator
android·android jetpack
指尖动听知识库14 小时前
嵌入式经典面试题之操作系统(三)
android·java·面试