在 Android 上测试 Kotlin 协程

文章目录

    • 官方文档
    • 在测试中调用挂起函数
    • TestDispatchers
      • StandardTestDispatcher
      • UnconfinedTestDispatcher
    • 注入测试调度程序
    • 设置主调度程序
    • 在测试之外创建调度程序
    • 创建您自己的 TestScope
    • 注入作用域

官方文档

https://developer.android.google.cn/kotlin/coroutines/test?hl=zh-cn
API 是 kotlinx.coroutines.test 库的一部分。如需访问这些 API,请务必添加相应工件作为项目的测试依赖项。

dependencies {testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
}

在测试中调用挂起函数

如需在测试中调用挂起函数,您必须位于协程中。由于 JUnit 测试函数本身并不是挂起函数,因此您需要在测试中调用协程构建器以启动新的协程。

suspend fun fetchData(): String {delay(1000L)return "Hello world"
}@Test
fun dataShouldBeHelloWorld() = runTest {val data = fetchData()assertEquals("Hello world", data)
}

TestDispatchers

TestDispatchers 是用于测试的 CoroutineDispatcher 实现。如果要在测试期间创建新的协程,您需要使用 TestDispatchers,以使新协程的执行可预测。

注意:新协程可直接在测试主体中创建,也可在测试中所调用的任何代码中创建(例如在测试的对象中)。
TestDispatcher 有两种可用的实现:StandardTestDispatcher 和 UnconfinedTestDispatcher,可分别对新启动的协程执行不同的调度。两者都使用 TestCoroutineScheduler 来控制虚拟时间并管理测试中正在运行的协程。

一个测试中只能使用一个调度器实例,且所有 TestDispatchers 应共用该调度器。如需了解如何共用调度器,请参阅注入测试调度程序。

为了启动顶级测试协程,runTest 会创建一个 TestScope,它是 CoroutineScope 的实现,将始终使用 TestDispatcher。如果未指定,TestScope 将默认创建 StandardTestDispatcher,并将其用于运行顶级测试协程。

StandardTestDispatcher

@Test
fun standardTest() = runTest {val userRepo = UserRepository()launch { userRepo.register("Alice") }launch { userRepo.register("Bob") }assertEquals(listOf("Alice", "Bob"), userRepo.getAllUsers()) // ❌ Fails
}

可通过多种方式让出测试协程,以让排队的协程运行。所有以下调用都可在返回之前让其他协程在测试线程上运行:

advanceUntilIdle:在调度器上运行所有其他协程,直到队列中没有任何内容。这是一个不错的默认选择,可让所有待处理的协程运行,适用于大多数测试场景。
advanceTimeBy:将虚拟时间提前指定时长,并运行已调度为在该虚拟时间点之前运行的所有协程。
runCurrent:运行已调度为在当前虚拟时间运行的协程。

UnconfinedTestDispatcher

如果在 UnconfinedTestDispatcher 上启动新协程,系统会在当前线程上快速启动。也就是说,这些协程会立即开始运行,而不会等待其协程构建器返回。在许多情况下,这种调度行为会使测试代码更加简单,因为您无需手动让出测试线程即可让新协程运行。

@Test
fun unconfinedTest() = runTest(UnconfinedTestDispatcher()) {val userRepo = UserRepository()launch { userRepo.register("Alice") }launch { userRepo.register("Bob") }assertEquals(listOf("Alice", "Bob"), userRepo.getAllUsers()) // ✅ Passes
}

注入测试调度程序

设置主调度程序

在本地单元测试中,封装 Android 界面线程的 Main 调度程序将无法使用,因为这些测试是在本地 JVM 而不是 Android 设备上执行的。如果被测试代码引用主线程,它会在单元测试期间抛出异常。

在测试之外创建调度程序

class Repository(private val ioDispatcher: CoroutineDispatcher) { /* ... */ }class RepositoryTestWithRule {private val repository = Repository(/* What TestDispatcher? */)@get:Ruleval mainDispatcherRule = MainDispatcherRule()@Testfun someRepositoryTest() = runTest {// Test the repository...// ...}
}

创建您自己的 TestScope

class SimpleExampleTest {val testScope = TestScope() // Creates a StandardTestDispatcher@Testfun someTest() = testScope.runTest {// ...}
}

注入作用域

如果有类创建需要您在测试期间控制的协程,则可以将协程作用域注入到该类中,并在测试中将其替换为 TestScope

class UserState(private val userRepository: UserRepository,private val scope: CoroutineScope,
) {private val _users = MutableStateFlow(emptyList<String>())val users: StateFlow<List<String>> = _users.asStateFlow()fun registerUser(name: String) {scope.launch {userRepository.register(name)_users.update { userRepository.getAllUsers() }}}
}
class UserStateTest {@Testfun addUserTest() = runTest { // this: TestScopeval repository = FakeUserRepository()val userState = UserState(repository, scope = this)userState.registerUser("Mona")advanceUntilIdle() // Let the coroutine complete and changes propagateassertEquals(listOf("Mona"), userState.users.value)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/112910.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytorch搭建DTLN降噪算法

前面介绍了几种轻量级网路结构的降噪做法&#xff0c;本文介绍DTLN—一种时频双核心网络降噪做法。 AI-GruNet降噪算法 AI-CGNet降噪算法 AI-FGNet降噪算法 Pytorch搭建实虚部重建AI-GruNet降噪算法 一、模型结构 DTLN来自[2005.07551] Dual-Signal Transformation LSTM N…

ChatGLM2-INT4 + Lora 结构适配和改造

Lora 是目前公认的最好的微调方法&#xff0c;一方面&#xff0c;它并不像AdapterTuning 一样&#xff0c;改变原有模型的架构&#xff0c;不便于在不同框架之间迁移&#xff1b;另一方面&#xff0c;它不像 PTuning 一样改变所有任务下的单词生成概率&#xff0c;严重破坏已习…

nginx配合tomcat、resin等java应用服务器提供java支持

首先探讨一下为什么要使用nginx&#xff1a; 1、类似于apacheresin&#xff0c;nginx用于提供静态页面服务&#xff0c;比java服务器要强。虽然这些java服务器的性能都不赖&#xff0c;tomcat新版甚至还支持了epoll&#xff0c;但是用nginx来处理静态文件是一定比这些服务器更…

macos使用搭建算法竞赛c/c++的g++/gcc编译环境(homebrew,含万能头,改环境变量,vscode/clion可用)

文章目录 1、homebrew安装2、安装g3、改环境变量 1、homebrew安装 我没改镜像&#xff0c;直接网上脚本一键安装的&#xff0c;具体命令忘了&#xff0c;可能是这个 反正装这个的方法很多&#xff0c;网上一搜都有。 成功装上homebrew就行。 /bin/bash -c "$(curl -fsSL…

微信小程序6

一、什么是后台交互&#xff1f; 在小程序中&#xff0c;与后台交互指的是小程序前端与后台服务器之间的数据通信和请求处理过程。通过与后台交互&#xff0c;小程序能够获取服务器端的数据、上传用户数据、发送请求等。 与后台交互可以通过以下方式实现&#xff1a; 发起网络请…

redis的cluster

1.我们的哨兵模式中&#xff0c;当主节点挂掉以后&#xff0c;此时哨兵会重新进行选举&#xff0c;选举出新的主节点去对外提供写服务 在选举的过程中,他redis整个集群是不提供写服务的 &#xff08;因为此时我们哨兵对外提供写服务的只有Master&#xff09; 2.我们单节点的red…

ESP32集成开发环境Espressif-IDE安装 – Windows

陈拓 2023/10/15-2023/10/16 1. 概述 Espressif IDE是一个基于Eclipse CDT的集成开发环境&#xff08;IDE&#xff09;&#xff0c;用于使用ESP-IDF框架开发物联网应用程序。这是一个专门为ESP-IDF构建的独立定制IDE。Espressif IDE附带了IDF Eclipse插件、重要的Eclipse CDT插…

【数据结构】线性表(八)队列:顺序队列及其基本操作(初始化、判空、判满、入队、出队、存取队首元素)

文章目录 一、队列1. 定义2. 基本操作 二、顺序队列0. 顺序表1. 头文件和常量2. 队列结构体3. 队列的初始化4. 判断队列是否为空5. 判断队列是否已满6. 入队7. 出队8. 存取队首元素9. 主函数10. 代码整合 堆栈Stack 和 队列Queue是两种非常重要的数据结构&#xff0c;两者都是特…

美格智能出席无锡智能网联汽车生态大会,共话数字座舱新势力

10月20日&#xff0c;2023世界物联网博览会期间&#xff0c;以“智 行天下 启未来”为主题的2023无锡智能网联汽车生态大会暨域控制器及智能座舱论坛在无锡举行。大会邀请行业权威专家&#xff0c;多家知名企业重磅嘉宾出席&#xff0c;融汇智能网联汽车思想智慧、创新技术、产…

微信小程序连接数据库与WXS的使用

微信小程序连接数据库与WXS的使用 1.搭建数据库连接,使用后端获取数据1.请求方式的封装2.化一下代码&#xff0c;这样写太繁琐了3.前端代码 四、WXS的使用1..解决数据显示数字问题2. 解决统计人数问题3.解决时间进制问题 ) 1.搭建数据库连接,使用后端获取数据 为了后期方便维护…

李m圆申论

听话出活 3小时 /处理7500字 /一共5题 /写出2200字 字写得好看点&#xff0c;符号也算字数&#xff0c;占一个格 基本思路&#xff1a;考什么范围答什么 。。。落后&#xff1b;资源闲置、缺乏 申论&#xff1a; 作文题&#xff1a;举例子 处理材料 摘抄&#xff1a; 有人出…

centos或aws linux部署java应用,环境搭建shell

目录 设置root密码开启密码登录安装docker安装nginx设置nginx自启动nginx配置https配置http集群tcp集群 安装docker设置docker自启动修改docker基础配置创建docker网关docker安装mysql单机版本主从版本 docker安装redis设置密码&#xff1a;不要密码&#xff1a; docker安装rab…

基础MySQL的语法练习

基础MySQL的语法练习 create table DEPT(DEPTNO int(2) not null,DNAME VARCHAR(14),LOC VARCHAR(13) );alter table DEPTadd constraint PK_DEPT primary key (DEPTNO);create table EMP (EMPNO int(4) primary key,ENAME VARCHAR(10),JOB VARCHAR(9),MGR …

【机器学习】集成模型/集成学习:多个模型相结合实现更好的预测

1. 概述 1.1 什么是集成模型/集成学习 "模型集成"和"集成学习"是相同的概念。它们都指的是将多个机器学习模型组合在一起&#xff0c;以提高预测的准确性和稳定性的技术。通过结合多个模型的预测结果&#xff0c;集成学习可以减少单个模型的偏差和方差&am…

13.3测试用例进阶

一.测试对象划分 1.界面测试(参考软件规格说明书和UI视觉稿) a.什么是界面 1)WEB站(浏览器) 2)app 3)小程序 4)公众号 b.测试内容 1)界面内容显示的一致性,完整性,准确性,友好性.比如界面内容对屏幕大小的自适应,换行,内容是否全部清晰展示. 2)验证整个界面布局和排版…

RunnerGo 支持UI自动化的测试平台

RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块&#xff0c;覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selenium浏览器自动化方案构建&#xff0c;内嵌高度可复用的测试脚本&#xff0c;测试团队无需复杂的代码编写即可开展低代码的自动化…

Leetcode——字符

520. 检测大写字母 class Solution { public:bool detectCapitalUse(string word) {int big 0, small 0, len word.length();for (int i 0; i < len; i) {if (word[i] > 65 && word[i] < 90) {big;}else {small;}}if (big len || small len) {return tr…

工业电子中的深力科分享一款PWM控制器 KA3525A

关于PWM控制器&#xff1a; PWM控制器是一种用于控制电机或其他设备的电路&#xff0c;它通过改变脉冲宽度调制&#xff08;PWM&#xff09;信号的占空比来控制设备的输出。PWM控制器可以使用单片机或开发板等设备来实现&#xff0c;通过设定占空比&#xff0c;可以轻松地控制…

关于数据库连接池和线程,记录几个问题

文章目录 1.HirakiPool - Connection is not available, request timed out after2.在一个线程内&#xff0c;调用多次dataSource.getConnection()这是为什么呢&#xff1f;是谁来实现的线程内连接唯一呢&#xff1f; 1.HirakiPool - Connection is not available, request tim…

【微信小程序调试工具试用】

【微信小程序调试工具试用】 试用大佬开发的dll拿到某物小程序sign签名 &#xff08;过于简单 大佬勿喷&#xff09;本次工具分享到此结束 什么是爬虫逆向&#xff1f; 试用大佬开发的dll拿到某物小程序sign签名 &#xff08;过于简单 大佬勿喷&#xff09; 1 如图 下面小程序…