Android中使用Robolectric测试点击事件(不需要手机)
文章目录
- 一、前言
- 二、简单示例
- 三、注意事项
- 四、另一种写法
- 五、拓展
- 六、参考文档
一、前言
Robolectric 是一个由 Google 维护的开源 Android 测试框架,它允许你以 Android 运行时环境运行单元测试。
Robolectric 提供了一个模拟 Android 运行时环境,允许你测试你的代码是否正确地使用 Android API。
所以在不依赖于手机的情况下可以对android项目进行测试。当然也可以在有手机的时候对Android项目进行测试
二、简单示例
以下代码源自官方文档,并进行简单完善。
文件位于src/app/test/下面
import android.content.Intent
import android.widget.Button
import com.example.myapplication.R
import com.example.myapplication.hilt.App
import com.example.myapplication.material.MaterialTestActivity
import com.example.myapplication.roll.PaintedScrollActivity
import junit.framework.TestCase.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.Shadows.shadowOf
import org.robolectric.annotation.Config@RunWith(RobolectricTestRunner::class)
@Config(application = App::class, sdk = [28])
class RobolectricTest {// @get:Rule
// @JvmField
// val executorRule = InstantTaskExecutorRule()@Testfun clickingLogin_shouldStartLoginActivity() {Robolectric.buildActivity(MaterialTestActivity::class.java).use { controller ->controller.setup() // Moves the Activity to the RESUMED stateval activity = controller.get()activity.findViewById<Button>(R.id.button).performClick()val expectedIntent = Intent(activity, PaintedScrollActivity::class.java)val actual = shadowOf(RuntimeEnvironment.getApplication()).nextStartedActivity//新版写法使用如下方式//val actual = shadowOf(androidx.test.core.app.ApplicationProvider.getApplicationContext<App>()).nextStartedActivityprintln("YM----->,actual--> ${actual.component?.className}---->expectedIntent.name:${expectedIntent.component?.className}")assertEquals(expectedIntent.component, actual.component)}}}
这里需要注意的是需要添加
@Config(application = App::class, sdk = [28])
其中App是应用的Application文件。否则会有各种问题,最主要是提示不是主线程的问题。如果没有Application的话,可以使用另外一种方式。这种方式需要添加如下依赖
testImplementation "androidx.arch.core:core-testing:2.1.0"
然后添加以下代码
@get:Rule@JvmFieldval executorRule = InstantTaskExecutorRule()
不过@Config也需要添加版本
@Config(sdk = [28])
三、注意事项
后面又经过测试,发现上述代码即使不在Config中添加App也可以运行,如
@Config(application = App::class, sdk = [28]) // X error
//改为
@Config(sdk = [28]) // 也是可以运行的
同时下面代码也没有
// @get:Rule
// @JvmField
// val executorRule = InstantTaskExecutorRule()
根据官网来说,如果不设置App的话,会自动使用程序定义的Application,但是之前代码确实一直运行失败,这里留作记录。
参考链接
四、另一种写法
这里提供另外一个测试示例,需要注意的是,其中断言可以使用以下任意一种库
testImplementation 'com.google.truth:truth:1.1.3'
testImplementation 'org.assertj:assertj-core:3.24.2'
以下是不同断言的区别:
| 断言库 | 适用场景 | 优势 | 适用语言 |
|---|---|---|---|
| JUnit Assertions | 最基础的测试 | 轻量级,适合简单测试 | Java, Android |
| Google Truth | Android 开发 | 可读性好,官方推荐 | Java, Android |
| AssertJ | Java 后端、复杂测试 | 功能最强大,链式断言 | Java |
| Hamcrest | 传统 Java | JUnit 4 时代流行 | Java |
| Kotest/Strikt | Kotlin 测试 | Kotlin DSL 语法更友好 | Kotlin |
其中使用AssertJ的话需要额外依赖Junit库
@Testfun locationListenerShouldBeUnregisteredInCreatedState() {// GIVENval controller = Robolectric.buildActivity<MaterialTestActivity>(MaterialTestActivity::class.java)controller.setup()// WHENcontroller.pause().stop()// THENassertThat(controller.get().locationListener).isNull()}@Testfun locationListenerShouldBeUnregisteredInCreatedState2() {// GIVENval scenario = ActivityScenario.launch<MaterialTestActivity>(MaterialTestActivity::class.java)// WHENscenario.moveToState(Lifecycle.State.CREATED)// THENscenario.onActivity { activity ->assertThat(activity.locationListener).isNull()}}
五、拓展
关于mock的含义,mock的作用的在测试过程中对某些功能进行模拟,保证流程能够执行下去,但是数据并不对。比如说假如自己写的一个类,需要传递Context才能保证不崩溃,那么可以使用mock进行模拟。
六、参考文档
- Robolectric 策略
- robolectric
- 构建本地单元测试
- Robolectric 4.0
- AndroidX Test
- mockito
- mockito-kotlin
相关文章:
Android中使用Robolectric测试点击事件(不需要手机)
文章目录 一、前言二、简单示例三、注意事项四、另一种写法五、拓展六、参考文档 一、前言 Robolectric 是一个由 Google 维护的开源 Android 测试框架,它允许你以 Android 运行时环境运行单元测试。 Robolectric 提供了一个模拟 Android 运行时环境,允…...
安卓开发相机功能
相机功能 安卓中的相机调用功能也经历了很多的方案升级,目前可选的官方方案是CameraX、Camera2、Camera(废弃),还有一些第三方免费或者是付费的相机库。对于大多数开发者,建议使用 CameraX。 CameraX CameraX 是 An…...
机器学习:监督学习、无监督学习和强化学习
机器学习(Machine Learning, ML)是人工智能(AI)的一个分支,它使计算机能够从数据中学习,并在没有明确编程的情况下执行任务。机器学习的核心思想是使用算法分析数据,识别模式,并做出…...
基于vue3和flask开发的前后端管理系统(一):项目启动准备
准备工作 我们需要准备以下工具 vue3:构建前端 tailwind css:样式库vite:快速构建vue项目pinia :vue3 的事件管理器 flask:后端代码Mysql:数据库 heidisql:数据库图形化界面 vscode࿱…...
一、MySQL备份恢复
一、MySQL备份恢复 1.1 MySQL日志管理 数据库中数据丢失或被破坏可能原因 误删除数据库 数据库工作时,意外断电或程序意外终止 由于病毒造成的数据库损坏或丢失 文件系统损坏后,系统进行自检操作 升级数据库时,命令语句不严格 设备故…...
DeepSeek崛起:如何在云端快速部署你的专属AI助手
在2025年春节的科技盛宴上,DeepSeek因其在AI领域的卓越表现成为焦点,其开源的推理模型DeepSeek-R1擅长处理多种复杂任务,支持多语言处理,并通过搜索引擎获取实时信息。DeepSeek因其先进的自然语言处理技术、广泛的知识库和高性价比…...
SQLite Alter 命令详解
SQLite Alter 命令详解 SQLite 是一种轻量级的数据库,广泛用于各种嵌入式系统、移动应用和小型项目。SQLite 的ALTER TABLE命令用于修改已存在的表结构,包括添加、删除或修改列,以及重命名表等操作。本文将详细解析SQLite的ALTER TABLE命令&…...
2025 聚合易支付完整版PHP网站源码
源码介绍 2025 聚合易支付完整版PHP网站源码 PHP版本:PHP74 源码上传服务器,解压访问域名即可安装 安装完成后一定要设置伪静态 源码里面nginx.txt 就是伪静态 然后复制粘贴到伪静态里面保存即可 部分截图 源码获取 2025 聚合易支付完整版PHP网站源码…...
Android开发Android调web的方法
Android开发Android调web的方法 一般都是web调Android,很少Android调web方法。 我用的是AgentWeb。它内核也是webview。 直接上代码: mAgentWeb.getJsAccessEntrace().quickCallJs("adLookSuccessAndroid",event.getType());它的意思是&am…...
FastGPT 源码:基于 LLM 实现 Rerank (含Prompt)
文章目录 基于 LLM 实现 Rerank函数定义预期输出实现说明使用建议完整 Prompt 基于 LLM 实现 Rerank 下边通过设计 Prompt 让 LLM 实现重排序的功能。 函数定义 class LLMReranker:def __init__(self, llm_client):self.llm llm_clientdef rerank(self, query: str, docume…...
字节跳动发布 Trae AI IDE!支持 DeepSeek R1 V3,AI 编程新时代来了!
3 月 3 日,字节跳动重磅发布国内首款 AI 原生集成开发环境(AI IDE)——Trae 国内版! Trae 不只是一个传统的 IDE,它深度融合 AI,搭载 doubao-1.5-pro 大模型,同时支持DeepSeek R1 & V3&…...
windows下安装Open Web UI
windows下安装openwebui有三种方式,docker,pythonnode.js,整合包. 这里我选择的是第二种,非docker. 非Docker方式安装 1. 安装Python: 下载并安装Python 3.11,建议安装路径中不要包含中文字符,并勾选“Add python 3.11 to Path”选项。 安…...
论文阅读 EEG-Inception
EEG-Inception: A Novel Deep Convolutional Neural Network for Assistive ERP-Based Brain-Computer Interfaces EEG-Inception是第一个集成Inception模块进行ERP检测的模型,它有效地结合了轻型架构中的其他结构,提高了我们方法的性能。 本研究的主要目…...
基于opencv消除图片马赛克
以下是一个基于Python的图片马赛克消除函数实现,结合了图像处理和深度学习方法。由于马赛克消除涉及复杂的图像重建任务,建议根据实际需求选择合适的方法: import cv2 import numpy as np from PIL import Imagedef remove_mosaic(image_pat…...
计算机毕业设计SpringBoot+Vue.js陕西民俗网(源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
【算法方法总结·三】滑动窗口的一些技巧和注意事项
【算法方法总结三】滑动窗口的一些技巧和注意事项 【算法方法总结一】二分法的一些技巧和注意事项【算法方法总结二】双指针的一些技巧和注意事项【算法方法总结三】滑动窗口的一些技巧和注意事项 【滑动窗口】 数组的和 随着 右边指针 移动一定是 非递减 的,就是 …...
IO的概念和标准IO函数
作业: 1.使用标准IO函数,实现文件的拷贝 #include <stdio.h>int main(int argc, char *argv[]) {// 检查是否提供了源文件和目标文件if (argc ! 3) {printf("Usage: %s <source_file> <destination_file>\n", argv[0]);re…...
tauri2+typescript+vue+vite+leaflet等的简单联合使用(一)
项目目标 主要的目的是学习tauri。 流程 1、搭建项目 2、简单的在项目使用leaflet 3、打包 准备项目 环境准备 废话不多说,直接开始 需要有准备能运行Rust的环境和Node,对于Rust可以参考下面这位大佬的文章,Node不必细说。 Rust 和…...
【流程图】在 .NET (WPF 或 WinForms) 中实现流程图中的连线算法
在 .NET (WPF 或 WinForms) 中实现流程图中的连线算法,通常涉及 图形绘制 和 路径计算。常见的连线方式包括 直线、折线 和 贝塞尔曲线。以下是几种方法的介绍和示例代码。 1. 直线连接(最简单) 适用场景: 两个节点之间没有障碍…...
IDEA集成DeepSeek,通过离线安装解决无法安装Proxy AI插件问题
文章目录 引言一、安装Proxy AI1.1 在线安装Proxy AI1.2 离线安装Proxy AI 二、Proxy AI中配置DeepSeek2.1 配置本地部署的DeepSeek(Ollama方式)2.2 通过第三方服务商提供的API进行配置 三、效果测试 引言 许多开发者尝试通过安装Proxy AI等插件将AI能力…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
