首页/新闻资讯/正文详情

【Jetpack Compose进阶学与练】第19课 单元测试与UI测试;ViewModel单元测试 + Compose界面测试基础

发布时间:2026/9/24 17:31:05 来源:云帆数科 栏目:资讯中心
【Jetpack Compose进阶学与练】第19课 单元测试与UI测试;ViewModel单元测试 + Compose界面测试基础
前言前面课程主要聚焦业务开发软件项目开发离不开测试。本节课学习区分单元测试(JVM本地) 和Instrumented仪器化UI测试(Android设备/模拟器)ViewModel单元测试Compose的界面测试基础使用test‑junit4以及compose‑testing。知识点清单区分单元测试test目录JVM运行无设备 vs 仪器化测试(androidTest目录模拟器/真机执行)ViewModel单元测试测试业务逻辑、状态流转使用Mock模拟仓库Compose UI测试ComposeTestRule节点查找、断言、模拟点击测试中隔离业务避免真实网络请求简单测试用例示例build.gradle 依赖testImplementation junit:junit:4.13.2 testImplementation org.mockito:mockito-core:5.14.2 androidTestImplementation androidx.test.ext:junit:1.2.1 androidTestImplementation androidx.compose.ui:ui-test-junit4:1.7.3 debugImplementation androidx.compose.ui:ui-test-manifest:1.7.3完整示例源码importandroidx.lifecycle.ViewModelimportandroidx.lifecycle.viewModelScopeimportkotlinx.coroutines.flow.MutableStateFlowimportkotlinx.coroutines.flow.StateFlowimportkotlinx.coroutines.launch//业务ViewModel计数器示例classCounterViewModel:ViewModel{privateval_countMutableStateFlow(0)valcount:StateFlowInt_countfunincrease(){viewModelScope.launch{_count.value_count.value1}}fundecrease(){viewModelScope.launch{_count.value_count.value-1}}}/** * ViewModel本地单元测试放在 test/ 目录JVM不需要模拟器 */importkotlinx.coroutines.test.runTestimportorg.junit.Assert.assertEqualsimportorg.junit.TestclassCounterViewModelTest{TestfuntestIncrease()runTest{valvmCounterViewModel()vm.increase()assertEquals(1,vm.count.value)}TestfuntestDecrease()runTest{valvmCounterViewModel()vm.decrease()assertEquals(-1,vm.count.value)}}/** * Compose UI仪器化测试示例androidTest目录模拟器运行 */importandroidx.compose.ui.test.junit4.createComposeRuleimportandroidx.compose.ui.test.onNodeWithTextimportandroidx.compose.ui.test.performClickimportorg.junit.Ruleimportorg.junit.TestclassCounterScreenUiTest{get:RulevalcomposeTestRulecreateComposeRule()TestfunuiCounter_clickAdd_increaseNumber(){//挂载Compose页面composeTestRule.setContent{//此处挂载对应的Counter UI页面}//模拟点击“”按钮composeTestRule.onNodeWithText().performClick()//断言界面上文本显示数字1composeTestRule.onNodeWithText(1).assertExists()}}逐行解读两套测试目录区别src/test 本地单元测试直接跑在电脑JVM上不需要Android设备适合ViewModel、Repository工具类业务逻辑但是不能调用Android系统SDKAPIAndroid框架类需要mock。src/androidTest 仪器化测试运行于模拟器或者真机上面可以真实执行Compose渲染用于UI自动化测试可以查找界面节点、模拟点击、输入文本、做界面断言。ViewModel单元测试要点ViewModel里面大量使用协程 viewModelScope 正式单元测试的时候要用 runTest 替换真实的Android主调度器runTest是kotlin‑coroutines‑test提供虚拟时间快进协程不需要sleep等待。测试原则尽量隔离不要访问真实网络、真实数据库使用mock模拟仓库返回数据保证用例稳定不受后端环境影响。Compose UI测试核心 ComposeTestRuleget:Rule val composeTestRule createComposeRule()setContent{}把要测试的Compose组件挂载到测试环境onNodeWithText(“”)通过文本找到UI上组件节点performClick()模拟用户点击assertExists() / assertDoesNotExist()界面断言判断该UI节点是否出现也可以使用 onNodeWithTag 给组件设置 Modifier.testTag(“btn_add”) 优先使用testTag避免后续修改文字导致测试用例失效。test‑manifestdebugImplementationui‑test‑manifest 只在debug编译生效提供Compose测试所需要的Activity不要加到release依赖打包会报错。测试的策略建议分层测试思路①优先写ViewModel业务逻辑单元测试test目录速度很快②Repository层测试③少量关键页面流程补充Compose UI仪器化测试UI测试运行速度慢模拟器开销大不要把全部测试都写UI自动化重点业务流程覆盖即可。容易踩坑❌ 在test本地单元测试直接调用Android SDK类ContextToast会直接抛异常本地JVM没有Android框架。❌ release版本引入ui‑test‑manifest打包编译报错必须是debugImplementation。❌ UI测试大量依靠文本查找节点后续产品修改按钮文字直接导致全部UI用例失效优先使用Modifier.testTag标记控件。❌ 测试用例里面写Thread.sleep()等待网络应当mock Repository返回假数据消除网络等待。✅ test目录ViewModel业务单元测试(JVM)androidTest目录Compose界面仪器化测试runTest虚拟协程时间优先testTag定位UI节点mock隔离外部IO与网络。多元化习题练习习题1【基础‑改错题】想在src/test目录单元测试里面直接调用Toast.makeText()运行直接报错为什么答案src/test运行环境是电脑本地JVM没有Android系统框架不能直接使用Android SDK API如果必须要需要mock模拟。解读本地单元测试适合纯kotlin业务逻辑Android系统相关逻辑放到仪器化测试。习题2【基础‑代码修改题】给一个Button设置测试标记testTag用于UI查找节点只写Modifier片段答案Modifier.testTag(btn_increase)解读测试代码使用onNodeWithTag(“btn_increase”)查找该控件不受按钮显示文字改动影响。习题3【进阶‑补充代码题】ViewModel测试当中runTest{}作用是什么答案runTest提供虚拟协程调度器接管协程执行可以快进虚拟时间不需要真实sleep等待延时任务专门用于协程相关单元测试。解读viewModelScope内部启动的协程在runTest环境下可以被测试框架管控。习题4【综合‑逻辑应用题】项目当中为什么不要全部写UI自动化测试优先ViewModel单元测试答案ViewModel单元测试跑于本地JVM速度快不需要模拟器稳定性好适合反复回归业务逻辑UI仪器化测试需要真机/模拟器运行速度慢页面改动之后容易导致测试脚本失效所以优先对业务逻辑层写单元测试UI自动化只覆盖少量核心业务流程。解读分层测试底层逻辑优先上层UI为辅。习题5【概念简答题】mock模拟Repository层返回数据主要目的是什么答案隔离真实后端网络测试不再依赖后端服务不管后端是否可用测试用例都可以稳定执行可以方便构造成功、失败、异常多种返回场景。解读解除外部环境依赖是单元测试的关键思想。本节课知识点总结两个测试目录src/test本地JVM单元测试src/androidTest真机/模拟器仪器化UI测试。ViewModel协程业务逻辑单元测试使用runTest虚拟协程时间尽量mock仓库隔离网络与IO。Compose UI测试依靠ComposeTestRulesetContent挂载组件查找节点模拟点击界面断言优先使用testTag不依赖显示文本。ui‑test‑manifest只能debugImplementation不能release打包引入。测试分层策略优先ViewModel、Repository业务单元测试少量核心流程补充UI自动化测试不要全部依赖UI测试。下一课预告第20课 KMP Compose‑Multiplatform基础一套UI跨Android、桌面

相关推荐

学术写作AI工具怎么选?TaoToken 统一 Key 接入 Cline 的 settings.json 配置与验证
学术写作AI工具怎么选?TaoToken 统一 Key 接入 Cline 的 settings.json 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 17:31:05

室内无人机为什么同时配UWB、TOF和气压计?
室内无人机为什么同时配UWB、TOF和气压计?

室内无人机为什么同时配UWB、TOF和气压计?有客户在需求表里同时列了三个东西:UWB定位、TOF定高、气压计定高。他问的是"能不能只用一个方案解决所有问题"。这个问题背后有一个核心误解:很多人以为UWB能定三维坐标,那Z轴… · 2026/9/24 17:30:47

用 Docker Compose 在群晖/飞牛 NAS 上部署 Cursor 文档 AI 大模型:TaoToken 统一 Key 接入 OpenAI API 的配置方案
用 Docker Compose 在群晖/飞牛 NAS 上部署 Cursor 文档 AI 大模型:TaoToken 统一 Key 接入 OpenAI API 的配置方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 17:30:47

纽约出租车流量预测实战:从数据清洗到LightGBM与LSTM模型全链路
纽约出租车流量预测实战:从数据清洗到LightGBM与LSTM模型全链路

简介:这份资源是面向计算机相关专业学生、教师及科研人员的纽约出租车流量预测项目完整包,可作为毕业设计、课程作业或项目立项演示的参考方案。项目基于Python实现,围绕交通流量时序预测展开,涵盖数据加载、模型构建、训练评估与… · 2026/9/24 18:05:27

C# WinForms图书管理系统实战:ADO.NET数据绑定与LocalDB开发全链路
C# WinForms图书管理系统实战:ADO.NET数据绑定与LocalDB开发全链路

简介:这是一套基于C# Windows窗体开发的图书信息管理系统实战项目,专为.NET初学者设计,覆盖WinForm界面开发、SQL Server数据库操作及经典三层架构(Model-BLL-DAL)实践,重点实现数据的增删查改核心功能。资… · 2026/9/24 18:05:27

C# IC卡读写实例源码解析:从APDU指令到硬件串口通信落地
C# IC卡读写实例源码解析:从APDU指令到硬件串口通信落地

简介:面向C#桌面应用开发者的IC卡硬件读写实例源码包,演示通过PC/SC接口与读卡器交互、按ISO 7816协议发送APDU命令完成选卡、读卡、写卡等核心流程,适合需要对接身份证、门禁卡或会员卡系统的初中级开发者参考。压缩包共49个文件&#xff0c… · 2026/9/24 18:05:27

YOLOv8车流量检测与计数系统实践:从模型选择到目标跟踪全流程
YOLOv8车流量检测与计数系统实践:从模型选择到目标跟踪全流程

简介:面向毕业设计、课设与计算机视觉入门的道路车流量检测系统完整资源包,基于YOLOv8算法和Python实现,可完成车辆实时检测与流量统计,适用交通监控、城市车流分析等场景。包内共307个文件,含126个Python源码、125个p… · 2026/9/24 18:05:27

汉赢酱酒运营中心创新能力怎么样,研发能力强吗
汉赢酱酒运营中心创新能力怎么样,研发能力强吗

顺应酱酒产业发展趋势,锚定行业使命与社会责任近年来,酱酒产业在消费升级浪潮中快速发展,大众对正宗酱酒的认知不断提升,市场对高品质、高性价比酱酒的需求持续增长,同时行业长期存在的乱象也逐渐凸显:大量… · 2026/9/24 18:05:27

MATLAB随机森林回归预测实战:从原理到源码包解析
MATLAB随机森林回归预测实战:从原理到源码包解析

简介:随机森林(RF)回归预测的MATLAB源代码实现,面向需要快速上手机器学习回归预测的工程师、科研人员和学生,适合技能层级从入门到进阶的读者。应用场景覆盖价格预测、销售额预测、出行流量预测、能耗预测、案发数量预… · 2026/9/24 18:05:14

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码