在 Android 上测试 Kotlin 数据流
文章目录
- 一 创建虚构数据提供方
- 二 在测试中断言数据流发出
- 测试期间持续收集
- 三 测试 StateFlow
- 使用 stateIn 创建的 StateFlow
转自:
https://developer.android.google.cn/kotlin/flow/test?hl=zh-cn#producer
与数据流进行通信的单元或模块的测试方式取决于受测对象使用数据流作为输入还是输出
- 如果受测对象观察到数据流,您可以在虚构依赖项中生成数据流,而这些可以通过测试进行控制
- 如果单元或模块公开了数据流,您可以读取并验证测试中的数据流所发出的一个或多个数据项
一 创建虚构数据提供方
当受测对象是数据流使用方时,一种常见的测试方法是用虚构实现替换提供方。
class MyFakeRepository : MyRepository {fun observeCount() = flow {emit(ITEM_1)}
}
@Test
fun myTest() {// Given a class with fake dependencies:val sut = MyUnitUnderTest(MyFakeRepository())// Trigger and verify...
}
二 在测试中断言数据流发出
1、某些测试,您只需要检查来自数据流的第一个发出项或有限数量的项
@Test
fun myRepositoryTest() = runTest {// Given a repository that combines values from two data sources:val repository = MyRepository(fakeSource1, fakeSource2)// When the repository emits a valueval firstItem = repository.counter.first() // Returns the first item in the flow// Then check it's the expected itemassertEquals(ITEM_1, firstItem)
}
2、如果该测试需要检查多个值,则调用 toList() 会使数据流等待数据源发出其所有值,然后以列表形式返回这些值
@Test
fun myRepositoryTest() = runTest {// Given a repository with a fake data source that emits ALL_MESSAGESval messages = repository.observeChatMessages().toList()// When all messages are emitted then they should be ALL_MESSAGESassertEquals(ALL_MESSAGES, messages)
}
3、对于需要更复杂地收集数据项或未返回有限数据项的数据流,您可使用 Flow API 选取并转换数据项。
// Take the second item
outputFlow.drop(1).first()// Take the first 5 items
outputFlow.take(5).toList()// Takes the first item verifying that the flow is closed after that
outputFlow.single()// Finite data streams
// Verify that the flow emits exactly N elements (optional predicate)
outputFlow.count()
outputFlow.count(predicate)
测试期间持续收集
在测试中使用虚构实现时,您可以创建一个收集协程,该协程会持续接收 Repository 中的值
class Repository(private val dataSource: DataSource) {fun scores(): Flow<Int> {return dataSource.counts().map { it * 10 }}
}class FakeDataSource : DataSource {private val flow = MutableSharedFlow<Int>()suspend fun emit(value: Int) = flow.emit(value)override fun counts(): Flow<Int> = flow
}
可以创建一个收集协程,该协程会持续接收 Repository 中的值。
@Test
fun continuouslyCollect() = runTest {val dataSource = FakeDataSource()val repository = Repository(dataSource)val values = mutableListOf<Int>()backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {repository.scores().toList(values)}dataSource.emit(1)assertEquals(10, values[0]) // Assert on the list contentsdataSource.emit(2)dataSource.emit(3)assertEquals(30, values[2])assertEquals(3, values.size) // Assert the number of items collected
}
由于此处 Repository 公开的数据流永远无法完成,因此收集它的 toList 调用永远不会返回。
使用 Turbine 库
第三方 Turbine 库提供了一个用于创建收集协程的便捷 API,以及用于测试数据流的其他便捷功能
@Test
fun usingTurbine() = runTest {val dataSource = FakeDataSource()val repository = Repository(dataSource)repository.scores().test {// Make calls that will trigger value changes only within test{}dataSource.emit(1)assertEquals(10, awaitItem())dataSource.emit(2)awaitItem() // Ignore items if needed, can also use skip(n)dataSource.emit(3)assertEquals(30, awaitItem())}
}
三 测试 StateFlow
StateFlow 是一种可观察的数据存储器,可以收集这种存储器来以数据流的形式观察它随时间变化的存储值
以下 ViewModel 会从 Repository 收集值,并在 StateFlow 中将值提供给界面
class MyViewModel(private val myRepository: MyRepository) : ViewModel() {private val _score = MutableStateFlow(0)val score: StateFlow<Int> = _score.asStateFlow()fun initialize() {viewModelScope.launch {myRepository.scores().collect { score ->_score.value = score}}}
}
此 Repository 的虚构实现可能如下:
class FakeRepository : MyRepository {private val flow = MutableSharedFlow<Int>()suspend fun emit(value: Int) = flow.emit(value)override fun scores(): Flow<Int> = flow
}
使用此虚构实现测试 ViewModel 时,您可以从虚构实现发出值,以在 ViewModel 的 StateFlow 中触发更新,然后对更新后的 value 断言:
@Test
fun testHotFakeRepository() = runTest {val fakeRepository = FakeRepository()val viewModel = MyViewModel(fakeRepository)assertEquals(0, viewModel.score.value) // Assert on the initial value// Start collecting values from the RepositoryviewModel.initialize()// Then we can send in values one by one, which the ViewModel will collectfakeRepository.emit(1)assertEquals(1, viewModel.score.value)fakeRepository.emit(2)fakeRepository.emit(3)assertEquals(3, viewModel.score.value) // Assert on the latest value
}
使用 stateIn 创建的 StateFlow
ViewModel 使用 MutableStateFlow 存储 Repository 中的数据流发出的最新值。这是一种常见的模式,通常通过使用 stateIn 运算符以更简单的方式实现,该运算符会将冷数据流转换为热 StateFlow:
class MyViewModelWithStateIn(myRepository: MyRepository) : ViewModel() {val score: StateFlow<Int> = myRepository.scores().stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), 0)
}
相关文章:

在 Android 上测试 Kotlin 数据流
文章目录 一 创建虚构数据提供方二 在测试中断言数据流发出测试期间持续收集 三 测试 StateFlow使用 stateIn 创建的 StateFlow 转自: https://developer.android.google.cn/kotlin/flow/test?hlzh-cn#producer 与数据流进行通信的单元或模块的测试方式取决于受测对…...

day43
今日内容 python操作MySQL(重要) SQL注入问题(安全相关的xss,csrf) 视图(了解) 触发器(了解) 事务(重要) 存储过程(了解) 内置函数(了解,很多) 流程控制(了解) 索引(重点) python操作MySQL MySQL本身就是一款c/s架构,有服务端、有客户端&…...

终端管理制度
1、总则 1.1、目的 为规范XXXXX单位员工在使用计算机终端过程中的行为,提高计算机终端的安全性,确保员工安全使用计算机终端,特制定本制度。 1.2、范围 本规定适用于在XXXXX单位使用计算机终端的所有员工,包括内部终端和外部终…...

视频相关学习笔记
YUV 和rgb一样是一种表示色彩的格式,Y表示亮度,UV表示色度(U是蓝色投影,V是红色投影),只有Y就是黑白的,所以这个格式的视频图片可以兼容黑白电视,所以彩色电视使用的都是YUV 存储方…...

神经网络中epoch、batch、batchsize区别
目录 1 epoch 2 batch 3 batchsize 4 区别 1 epoch 当数据集中的全部数据样本通过神经网络一次并且返回一次的过程即完成一次训练称为一个epoch。 当我们分批学习时,每次使用过全部训练数据完成一次Forword运算以及一次BP运算,称为完成了一次epoch。 epoch时期 = 所有训练…...

如何将Mysql数据库的表导出并导入到另外的架构
如何将Mysql数据库的表导出并导入到另外的架构 准备一、解决方法1.右键->导出->用mysqldump导出2.注意路径一般为:C:/Program Files/MySQL/MySQL Server 8.0/bin/mysqldump.exe和导出的sql文件位置3.右键->SQL脚本->运行SQL脚本4.找到SQL脚本并点击确定…...

【tio-websocket】9、服务配置与维护—TioConfig
场景 我们在写 TCP Server 时,都会先选好一个端口以监听客户端连接,再创建N组线程池来执行相关的任务,譬如发送消息、解码数据包、处理数据包等任务,还要维护客户端连接的各种数据,为了和业务互动,还要把这些客户端连接和各种业务数据绑定起来,譬如把某个客户端绑定到一…...

数据结构—线性表(下)
文章目录 6.线性表(下)(4).栈与队列的定义和ADT#1.ADT#2.栈的基本实现#3.队列的形式#4.队列的几种实现 (5).栈与队列的应用#1.栈的应用i.后缀表达式求值ii.中缀表达式转后缀表达式 #2.队列的应用 (6).线性表的其他存储方式#1.索引存储#2.哈希存储i.什么是哈希存储ii.碰撞了怎么…...

apisix之插件开发,包含java和lua两种方式
https://download.csdn.net/download/tiantangpw/88475630 有ppt和springboot程序包,可以运行...

【面试经典150 | 链表】合并两个有序链表
文章目录 Tag题目来源题目解读解题思路方法一:递归方法二:迭代 写在最后 Tag 【递归】【迭代】【链表】 题目来源 21. 合并两个有序链表 题目解读 合并两个有序链表。 解题思路 一种朴素的想法是将两个链表中的值存入到数组中,然后对数组…...

【linux】麒麟v10安装Redis主从集群(ARM架构)
安装redis单示例的请看:麒麟v10安装Redis(ARM架构) 安装环境 HostnameIP addressmaster192.168.0.1slave1192.168.0.2slave2192.168.0.3 下载安装包 (三台都操作) wget https://repo.huaweicloud.com/kunpeng/…...

解决k8s删除名称空间无法强制删除的问题
问题起因:删除k8s名称空间的时候(此时名称空间下还有很多pod)一直删不掉,被我强行ctrl c了, 问题表象:然后就出现下面这悲催的一幕了,两个名称空间一直处于Terminating了 [rootmaster02 ~]# ku…...

华为---DHCP中继代理简介及示例配置
DHCP中继代理简介 IP动态获取过程中,客户端(DHCP Client)总是以广播(广播帧及广播IP报文)方式来发送DHCPDISCOVER和DHCPREQUEST消息的。如果服务器(DHCP Server)和 客户端不在同一个二层网络(二…...

五、W5100S/W5500+RP2040树莓派Pico<UDP Client数据回环测试>
文章目录 1. 前言2. 协议简介2.1 简述2.2 优点2.3 应用 3. WIZnet以太网芯片4. UDP Client回环测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 UDP是一种无连接的网络协议,它提供了一种简单的、不可靠的方式来…...

死锁Deadlock
定义 死锁是指两个或多个线程互相持有对方所需的资源,从而导致它们无法继续执行的情况。如下图所示,现有两个线程,分别是线程A及线程B,线程A持有锁A,线程B持有锁B。此时线程A想获取锁B,但锁B需等到线程B的结…...

【spark客户端】Spark SQL CLI详解:怎么执行sql文件、注释怎么写,支持的文件路径协议、交互式模式使用细节
文章目录 一. Spark SQL Command Line Options(命令行参数)二. The hiverc File1. without the -i2. .hiverc 介绍 三. 支持的路径协议四. 支持的注释类型五. Spark SQL CLI交互式命令六. Examples1. running a query from the command line2. setting Hive configuration vari…...

虹科干货 | HK-TrueNAS版本大揭秘!一文教您如何选择合适的TrueNAS软件
文章来源:虹科网络基础设施 阅读原文:https://mp.weixin.qq.com/s/Iv0zDDmiDgE9vEGlAZs-sg 1.导语 TrueNAS是虹科iXsystems 设计和开发的NAS 操作系统,提供许多功能,例如文件存储、虚拟机 (VM) 和媒体服务器。它基于…...

前端html+css+js实现的2048小游戏,很完善。
源码下载地址 支持:远程部署/安装/调试、讲解、二次开发/修改/定制 逻辑用的是JavaScript,界面用canvas实现,暂时还没有添加动画。 视频浏览地址...

学习通签到
要在Vue中使用H5lock.js,首先需要将H5lock.js引入到项目中。可以通过以下步骤来使用: 1. 将H5lock.js文件保存到项目中的某个目录下,例如src/assets文件夹。 2. 在需要使用H5lock.js的组件中,通过import语句将H5lock.js引入进来…...

target采退、测评养号购物下单操作教程
1.点击右上角的Create account注册账号 2.填写账号信息 3. 进入自己需要购买的商品页面 点击pick it up购买 4. 进入购物车页面选择快递方式和地址后点击 check out按钮 5. 之后会提示绑定XYK,这里我是用虚拟XYK开卡平台进行支付的. 6. 确认订单无误后点击Place you…...

SEACALL海外呼叫中心系统的优势包括
SEACALL海外呼叫中心系统的优势包括 封卡封号问题解决 海外呼叫中心系统通过API开放平台能力,定制电话营销系统,提供多项功能如自动拨打、智能应答、真人语音交互等,帮助企业克服员工离职率高、客户资源流失严重等挑战。 - 高级管理者操控 …...

Painter:使用视觉提示来引导网络推理
文章目录 1. 论文2. 示意图3. 主要贡献4. 代码简化 1. 论文 paper:Images Speak in Images: A Generalist Painter for In-Context Visual Learning github:https://github.com/baaivision/Painter 2. 示意图 3. 主要贡献 在 In-context Learning 中,作为自然语言…...

Fedora Linux 38 安装数学动画制作工具manimgl工具包
manimgl可以制作数学动画,它使用的是Python编程语言。 这里介绍他在Fedora Linux 38下的安装过程。 1. sudo dnf update 2. sudo dnf install python3-devel python3-pip python3-tools -y 3. sudo dnf install python3-numpy python3-scipy python3-sympy -y …...

行业追踪,2023-10-26
自动复盘 2023-10-26 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...

Android 和 iOS APP 测试的那些区别
目前市面上主流的移动操作系统就是 Android 和 iOS 两种,移动端测试本身就跟 Web 应用测试有自己的专项测试,比如安装、卸载、升级、消息推送、网络类型测试、弱网测试、中断测试、兼容性测试等都是区别于 Web 应用需要关注的测试领域。 那么࿰…...

利用nicegui开发ai工具示例
from fastapi import FastAPI import uvicorn from nicegui import uiclass PipRequirement:def __init__(self):ui.label("依赖安装与依赖展示")class BasicSettings:def __init__(self):self.project_select ui.select(["test"], label"项目选择&q…...

HarmonyOS鸿蒙原生应用开发设计- 流转图标
HarmonyOS设计文档中,为大家提供了独特的流转图标,开发者可以根据需要直接引用。 开发者直接使用官方提供的流转图标内容,既可以符合HarmonyOS原生应用的开发上架运营规范,又可以防止使用别人的图标侵权意外情况等,减…...

postgresql14管理(六)-备份恢复
定义 备份(backup):通过物理复制或逻辑导出的方式,将数据库的文件或结构和数据拷贝到其他位置进行存储; 还原(restore):是一种不完全的恢复。使用备份文件将数据库恢复到备份时的状…...

配置Sentinel 控制台
1.遇到的问题 服务网关 | RuoYi 最近调试若依的微服务版本需要用到Sentinel这个组件,若依内部继承了这个组件连上即用。 Sentinel是阿里巴巴开源的限流器熔断器,并且带有可视化操作界面。 在日常开发中,限流功能时常被使用,用…...

【漏洞复现】酒店宽带运营系统RCE
漏洞描述 安美数字 酒店宽带运营系统 server_ping.php 远程命令执行漏洞 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益ÿ…...