Kotlin Android单元测试MockK指南
目录
- MockK 简介
- 环境配置
- 基础用法
- 高级用法
- Android 特有场景
- 最佳实践
1. MockK 简介
MockK 是一个专为 Kotlin 设计的 Mocking 框架,支持协程、扩展函数、对象声明(object
)等 Kotlin 特性。相比 Mockito,它提供更自然的 Kotlin API,解决了 final
类无法 Mock 的问题。
核心优势:
- 原生支持 Kotlin 特性(如协程、
object
单例)。 - 简洁的 DSL 语法。
- 支持静态方法、构造函数 Mock。
2. 环境配置
在 build.gradle
中添加依赖:
// 模块级 build.gradle
dependencies {testImplementation "io.mockk:mockk:1.13.8" // 基础库testImplementation "io.mockk:mockk-agent-jvm:1.13.8" // 解决某些 JDK 版本兼容性问题testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" // JUnit 5(可选)
}
注意:若使用 JUnit 4,需添加
testImplementation "io.mockk:mockk-android:1.13.8"
。
3. 基础用法
3.1 创建 Mock 对象
val service = mockk<MyService>() // 创建 Mock 对象
3.2 设置行为 (Stubbing)
// 模拟方法返回值
every { service.fetchData(any()) } returns "Mocked Data"// 模拟抛出异常
every { service.fail() } throws RuntimeException("Error")
3.3 验证调用
service.fetchData(123)
verify { service.fetchData(123) } // 验证方法是否被调用// 验证调用次数
verify(exactly = 1) { service.fetchData(any()) }
3.4 参数匹配器
// 匹配任何参数
every { service.fetchData(any()) } returns "Data"// 捕获参数
val slot = slot<Int>()
every { service.saveData(capture(slot)) } just Runsservice.saveData(123)
assert(slot.captured == 123)
4. 高级用法
4.1 模拟静态方法与对象声明
// Mock object 单例
object Singleton {fun doWork() = "Real"
}mockkObject(Singleton)
every { Singleton.doWork() } returns "Mocked"// Mock 静态方法
mockkStatic(MyUtils::class)
every { MyUtils.format(any()) } returns "Formatted"
清理资源:
@After
fun tearDown() {unmockkAll() // 或 unmockkObject(Singleton)
}
4.2 模拟构造函数
class MyHelper(val config: String)mockkConstructor(MyHelper::class)
every { anyConstructed<MyHelper>().config } returns "Mocked Config"val helper = MyHelper("Real")
assert(helper.config == "Mocked Config")
4.3 协程支持
使用 coEvery
和 coVerify
处理挂起函数:
class Repository {suspend fun loadData() = "Real Data"
}val repo = mockk<Repository>()
coEvery { repo.loadData() } returns "Mocked Data"runBlocking {val data = repo.loadData()assert(data == "Mocked Data")coVerify { repo.loadData() }
}
4.4 Spy:部分模拟真实对象
val spy = spyk<RealClass>() // 默认调用真实方法every { spy.mockedMethod() } returns "Mocked"
5. Android 特有场景
5.1 测试 ViewModel
class MyViewModel(private val repo: Repository) : ViewModel() {private val _data = MutableLiveData<String>()val data: LiveData<String> = _datafun load() {viewModelScope.launch {_data.value = repo.fetchData()}}
}// 测试代码
@Test
fun testViewModel() = runTest { // 使用 TestCoroutineDispatcherval repo = mockk<Repository>()coEvery { repo.fetchData() } returns "Test Data"val viewModel = MyViewModel(repo)viewModel.load()// 处理 LiveDataval observer = mockk<Observer<String>>()viewModel.data.observeForever(observer)verify(timeout = 1000) { observer.onChanged("Test Data") }
}
5.2 处理 Context
val context = mockk<Context>()
val res = mockk<Resources>()every { context.resources } returns res
every { res.getString(any()) } returns "Mocked String"
6. 最佳实践
- 避免过度 Mock:仅 Mock 外部依赖(如网络、数据库),不要 Mock 被测类内部行为。
- 使用清晰命名:如
userRepositoryMock
替代mockk<Repository>()
。 - 及时清理:在
@After
中调用unmockkAll()
避免测试间污染。 - 组合使用工具:结合
Truth
、Turbine
等库提升断言可读性。 - 优先使用真实对象:当依赖简单且无副作用时,直接使用真实对象而非 Mock。
实际开发中,建议结合具体场景选择最合适的 Mock 策略,确保测试既简洁又可靠。
相关文章:
Kotlin Android单元测试MockK指南
目录 MockK 简介环境配置基础用法高级用法Android 特有场景最佳实践 1. MockK 简介 MockK 是一个专为 Kotlin 设计的 Mocking 框架,支持协程、扩展函数、对象声明(object)等 Kotlin 特性。相比 Mockito,它提供更自然的 Kotlin A…...
C# lock
在C#中,lock关键字用于确保当一个线程位于给定实例的代码块中时,其他线程无法访问同一实例的该代码块。这是一种简单的同步机制,用来防止多个线程同时访问共享资源或执行需要独占访问的代码段(临界区),从而…...
《算法导论(第4版)》阅读笔记:p83-p85
《算法导论(第4版)》学习第 18 天,p83-p85 总结,总计 3 页。 一、技术总结 1. Strassen algorithm(施特拉森算法) 2.矩阵 (1)矩阵表示法 If we wish to refer to matrices without specifically writing out all their entries, we will use upperc…...
Go 后端中双 token 的实现模板
下面是一个典型的 Go 后端双 Token 认证机制 实现模板,使用 Gin 框架 JWT Redis,结构清晰、可拓展,适合实战开发。 项目结构建议 /utils├── jwt.go // Access & Refresh token 的生成和解析├── claims.go // 从请求…...

【拥抱AI】Deer-Flow字节跳动开源的多智能体深度研究框架
最近发现一款可以对标甚至可能超越GPT-Researcher的AI深度研究应用,Deer-Flow(Deep Exploration and Efficient Research Flow)作为字节跳动近期开源的重量级项目,正以其模块化、灵活性和人机协同能力引发广泛关注。该项目基于 La…...
第六天——贪心算法——字符串分隔
1. 题目 给定一个字符串 s,我们需要将其划分为尽可能多的部分,使得同一字母最多出现在一个部分中。 例如:字符串 "ababcc" 可以划分为 ["abab", "cc"],但要避免 ["aba", "bcc&quo…...
Python 条件语句详解
条件语句是编程中用于控制程序流程的基本结构,Python 提供了几种条件语句来实现不同的逻辑判断。 1. if 语句 最基本的条件语句形式: if 条件:# 条件为真时执行的代码块示例: age 18 if age > 18:print("你已经成年了")2. …...

前端获取用户的公网 IP 地址
可以使用免费的免费的公共服务网站 一:https://www.ipify.org/ 获取 JSON 格式的 IP 地址 // 旧地址不好使 // https://api.ipify.org/?formatjson // 新地址 https://api64.ipify.org/?formatjson 二:https://ipinfo.io/ https://ipinfo.io/ 三&a…...
在Maven中替换文件内容的插件和方法
在Maven中替换文件内容的插件和方法 Maven提供了几种方式来替换文件内容,以下是常用的插件和方法: 1. maven-replacer-plugin (推荐) 这是专门用于文件内容替换的插件,功能强大且灵活。 基本配置 <plugin><groupId>com.goog…...
符合Python风格的对象(再谈向量类)
再谈向量类 为了说明用于生成对象表示形式的众多方法,我们将使用一个 Vector2d 类,它与第 1 章中的类似。这一节和接下来的几节会不断实 现这个类。我们期望 Vector2d 实例具有的基本行为如示例 9-1 所示。 示例 9-1 Vector2d 实例有多种表示形式 &g…...

云电竞服务器 工作原理
云电竞服务器工作原理详解 一、核心架构原理 虚拟化资源池 通过 KVM/VMware 等虚拟化技术将物理服务器(含NVIDIA GPU集群)抽象为可动态分配的算力资源池,每个用户独享独立虚拟机实例,实现硬件资源的按需分配与隔离运行。 …...

【数据结构】线性表--队列
【数据结构】线性表--队列 一.什么是队列二.队列的实现1.队列结构定义:2.队列初始化函数:3.队列销毁函数:4.入队列函数(尾插):5.出队列函数(头删):6.取队头元素ÿ…...

[Vue3]语法变动
Vue3的语法相对比Vue2有不少改变,这篇讲一下基础语法在Vue3里的形式。 创建Vue对象 在脚手架项目中,index.html等资源不再编写代码,只作为一个容器。所有的页面代码都在.vue相关文件中进行编写,由main.js引入各个.vue文件渲染出页…...

Ubuntu服务器开启SNMP服务 监控系统配置指南 -优雅草星云智控简易化操作
Ubuntu服务器开启SNMP服务 & 监控系统配置指南 -优雅草星云智控简易化操作 一、Ubuntu服务器开启SNMP服务 步骤1:安装SNMP服务 sudo apt update sudo apt install snmp snmpd snmp-mibs-downloader -y 步骤2:配置SNMP(编辑配置文件&am…...

linux本地部署ollama+deepseek过程
1.Tags ollama/ollama GitHub 选择一个版本下载,我下的是0.5.12 2.tar解压该文件 3.尝试启动ollama ollama serve 4.查看ollama的版本 ollama -v 5.创建一个系统用户 ollama,不允许登录 shell,拥有一个主目录,并且用…...

从零开始实现大语言模型(十五):并行计算与分布式机器学习
1. 前言 并行计算与分布式机器学习是一种使用多机多卡加速大规模深度神经网络训练过程,以减少训练时间的方法。在工业界的训练大语言模型实践中,通常会使用并行计算与分布式机器学习方法来减少训练大语言模型所需的钟表时间。 本文介绍PyTorch中的一种…...

OpenCV进阶操作:指纹验证、识别
文章目录 前言一、指纹验证1、什么是指纹验证2、流程步骤 二、使用步骤(案例)三、指纹识别(案例)1、这是我们要识别的指纹库2、这是待识别的指纹图3、代码4、结果 总结 前言 指纹识别作为生物识别领域的核心技术之一,…...

网络安全-等级保护(等保) 2-5 GB/T 25070—2019《信息安全技术 网络安全等级保护安全设计技术要求》-2019-05-10发布【现行】
################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…...

3D生成新突破:阶跃星辰Step1X-3D开源,可控性大幅提升
Step1X-3D 是由 StepFun 联合 LightIllusions 推出的新一代 高精度、高可控性 3D资产生成框架。基于严格的 数据清洗与标准化流程,我们从 500万 3D资产 中筛选出 200万高质量数据,构建了 标准化的几何与纹理属性数据集,为3D生成提供更可靠的训…...

MySQL数据类型之VARCHAR和CHAR使用详解
在设计数据库字段时,字符串类型算是最常见的数据类型之一了,这篇文章带大家深入探讨一下MySQL数据库中VARCHAR和CHAR数据类型的基本特性,以及它们之间的区别。 VARCHAR类型 VARCHAR(Variable Character,可变长度字符…...
数字人 LAM 部署笔记
目录 windos踩坑 GitHub - aigc3d/LAM: [SIGGRAPH 2025] LAM: Large Avatar Model for One-shot Animatable Gaussian Head windos踩坑 nvidia-smi环境 cuda 11.8conda install -c "nvidia/label/cuda-11.8.0" cuda-toolkit conda create --name cuda11.8 -y pyth…...

《Docker 入门与进阶:架构剖析、隔离原理及安装实操》
1 docker 简介 1.1 Docker 的优点 Docker 是一款开放平台,用于应用程序的开发、交付与运行,能将应用和基础架构分离,实现软件快速交付 ,还能以统一方式管理应用和基础架构,缩短代码从编写到上线的时间。其核心优势如…...

基于Akamai云计算平台的OTT媒体点播转码解决方案
点播视频(VOD)流媒体服务依赖于视频流的转码来高效分发内容。在转码工作流程中,视频被转换为适合观看设备、网络条件和性能限制的格式。视频转码是计算密集型过程,因此最大化可用硬件上可转码的视频流数量是首要考虑因素。不同基础…...

【MySQL】02.数据库基础
1. 数据库的引入 之前存储数据用文件就可以了,为什么还要弄个数据库? 文件存储存在安全性问题,文件不利于数据查询和管理,文件不利于存储海量数据,文件在程序中控制不方便。而为了解决上述问题,专家们设计出更加利于…...

选错方向太致命,华为HCIE数通和云计算到底怎么选?
现在搞HCIE的兄弟越来越多了,但“数通和云计算,到底考哪个?”这问题,依旧让不少人头疼。 一个是华为认证的老牌王牌专业——HCIE数通,稳、系统、岗位多; 一个是新趋势方向,贴合云原生、数字化…...

经典启发算法【早期/启发式/HC爬山/SA模拟退火/TS禁忌搜/IA免疫 思想流程举例全】
文章目录 一、早期算法二、启发式算法三、爬山法HC3.1 基本思路3.2 伪代码 四、模拟退火SA4.1 算法思想4.2 基本流程4.3 再究原理4.3.1 Metropolis准则4.3.2 再理解 4.4 小Tips4.5 应用举例4.5.1 背包问题:分析:求解: 4.5.2 TSP问题ÿ…...

IntraWeb 16.0.2 + Bootstrap 4 居中布局实战(附源码+效果图)
前言 最近在优化一个 IntraWeb 16.0.2 项目时,发现默认布局方式不够灵活,尤其是在不同屏幕尺寸下对齐效果不佳。于是,我决定引入 Bootstrap 4 来实现 完美居中布局,并成功落地!今天就把完整的 源代码 实际效果图 分享…...
Spring 框架中适配器模式的五大典型应用场景
Spring 框架中适配器模式的应用场景 在 Spring 框架中,适配器模式(Adapter Pattern)被广泛应用于将不同组件的接口转化为统一接口,从而实现组件间的无缝协作。以下是几个典型的应用场景: 1. HandlerAdapter - MVC 请…...

【Java ee初阶】jvm(3)
一、双亲委派机制(类加载机制中,最经常考到的问题) 类加载的第一个环节中,根据类的全限定类名(包名类名)找到对应的.class文件的过程。 JVM中进行类加载的操作,需要以来内部的模块“类加载器”…...
C 语言多维数组:定义、初始化与访问的深度解析
各类资料学习下载合集 https://pan.quark.cn/s/8c91ccb5a474 在 C 语言中,我们已经熟悉了一维数组(存储线性数据)和二维数组(存储表格或矩阵数据)。但现实世界的数据结构往往更加复杂,例如表示空间中的点、图像数据、物理模拟的网格等。这时,就需要用到多维数…...