深入了解模拟和存根:提高单元测试质量的关键技术

news2024/12/27 20:00:06

一、引言

在进行单元测试时,我们经常会遇到对外部资源的依赖,如数据库、网络接口等。模拟(Mocking)和存根(Stubbing)是两种帮助我们模拟这些外部资源,使我们能够在隔离环境中测试单元的方法。在本文中,我们将详细介绍模拟和存根,以及如何在单元测试中使用它们。

二、模拟和存根是什么?

模拟和存根都是用来模拟外部资源的技术,但它们的关注点略有不同:

  1. 存根(Stubs):存根是用来提供预设行为的。它们在你调用方法时返回一个特定的值或抛出一个异常。

  2. 模拟(Mocks):模拟不仅提供预设行为,还能检查调用的次数、参数等。通常我们用模拟来验证一个对象是否正确地使用了另一个对象。

三、使用模拟和存根的例子

下面,我们将使用JavaScript中的流行测试库,Jest,来展示如何使用模拟和存根。

例1:使用存根

假设你有一个函数getUserName,它从数据库中获取用户的名字。你想要测试这个函数,但是不想依赖真实的数据库。

  1. async function getUserName(userId) {

  2. const user = await db.getUser(userId);

  3. return user.name;

  4. }

你可以使用Jest的jest.fn()方法来创建一个存根:

  1. const db = {

  2. getUser: jest.fn()

  3. };

  4. db.getUser.mockResolvedValue({ name: 'Alice' });

  5. expect(await getUserName(1)).toBe('Alice');

在这个例子中,我们创建了一个存根来代替db.getUser方法。这个存根总是返回一个具有名字"Alice"的用户。

例2:使用模拟

假设你有一个login函数,它调用了一个authentication服务来验证用户的凭据。你想要测试这个函数,但是你更关心它是否正确地调用了authentication服务。

  1. async function login(username, password) {

  2. return await authentication.authenticate(username, password);

  3. }

你可以使用Jest的jest.fn()方法来创建一个模拟:

  1. const authentication = {

  2. authenticate: jest.fn()

  3. };

  4. authentication.authenticate.mockResolvedValue(true);

  5. await login('Alice', 'password');

  6. expect(authentication.authenticate).toHaveBeenCalledWith('Alice', 'password');

在这个例子中,我们创建了一个模拟来代替authentication.authenticate方法。然后,我们使用toHaveBeenCalledWith方法来验证login函数是否正确地调用了authentication.authenticate方法。

四、结论

模拟和存根是单元测试中的重要工具。它们帮助我们创建隔离的测试环境,使我们能够集中测试代码的特定部分,而不必担心其他外部依赖项。

下面是一些更深入使用模拟和存根的示例:

例3:更复杂的存根行为

在有些情况下,你可能想要模拟一些更复杂的行为,例如抛出异常。你可以通过配置存根来实现这一点。

  1. const db = {

  2. getUser: jest.fn()

  3. };

  4. db.getUser.mockRejectedValue(new Error('User not found'));

  5. try {

  6. await getUserName(1);

  7. } catch (e) {

  8. expect(e.message).toBe('User not found');

  9. }

在这个例子中,我们配置存根在被调用时抛出一个错误。然后,我们在测试中捕获这个错误,并验证它的消息是否正确。

例4:模拟函数调用的次数

除了验证模拟函数是否被正确的参数调用,你还可以验证模拟函数被调用的次数。

  1. const authentication = {

  2. authenticate: jest.fn()

  3. };

  4. authentication.authenticate.mockResolvedValue(true);

  5. await login('Alice', 'password');

  6. await login('Bob', 'password');

  7. expect(authentication.authenticate).toHaveBeenCalledTimes(2);

在这个例子中,我们使用toHaveBeenCalledTimes方法来验证login函数是否调用了两次authentication.authenticate方法。

五、结语

模拟和存根是一种强大的工具,可以帮助你编写出更加健壮和可维护的单元测试。通过了解何时以及如何使用这些工具,你可以更有效地测试你的代码,而无需担心外部依赖的复杂性。希望以上的示例可以帮助你在实践中更好地理解和应用模拟和存根。

六、参考链接

  • Jest: https://jestjs.io/

  • Sinon (另一款支持存根和模拟的JavaScript测试库): http://sinonjs.org/

行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

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

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

相关文章

PyQt6--Python桌面开发(6.QLineEdit单行文本框)

QLineEdit单行文本框 import sys import time from PyQt6.QtGui import QValidator,QIntValidator from PyQt6.QtWidgets import QApplication,QLabel,QLineEdit from PyQt6 import uicif __name__ __main__:appQApplication(sys.argv)uiuic.loadUi("./QLine单行文本框.u…

618值得入手的平价好物清单,看完再买不吃亏!

即将到来的618年中购物狂欢节,无疑是一年一度的购物盛宴。为了让大家的购物体验更加愉悦和充实,我特地为大家精选了一系列好物。如果你也打算在618尽情购物,那就赶紧收藏这份清单吧! 一、舒适佩戴不伤耳——南卡骨传导耳机Runner…

MySQL数据库实验三

本文承接前面的俩次实验基础上完成,不过实现的都是基础操作的练习 目录 目录 前言 实验目的 实验要求 实验内容及步骤 updata操作 delete操作 alter操作 添加列 删除列 修改列的数据类型 要求实现 实验结果 代码结果 注意事项 思考题 总结 前言 本文是MySQL数据库…

有了Supervisor,再也不用担心程序撂挑子了!

目录 1. 概述 2. 问题场景 3. Supervisor 简介 4.部署流程 4.1. 安装 Supervisor 4.2. 自定义服务配置文件 4.3. 自定义应用配置文件 4.4. 启动 supervisord 服务进程 4.5. 启动 supervisorctl 客户端进程 4.6. 验证 supervisor 的监控重启特性 5. 高级特性 5.1. 进…

大模型微调之 在亚马逊AWS上实战LlaMA案例(七)

大模型微调之 在亚马逊AWS上实战LlaMA案例(七) 微调SageMaker JumpStart上的LLaMA 2模型 这是在us-west-2的测试结果。 展示了如何使用SageMaker Python SDK部署预训练的Llama 2模型,并将其微调到你的数据集,用于领域适应或指令…

Python注意事项【自我维护版】

各位大佬好 ,这里是阿川的博客 , 祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 本篇博客在之前的博客上进行的维护 创建Python…

Java转Kotlin调用JNI方法异常

一、背景 Java调用JNI方法时没有任何问题,但是使用Java转Kotlin以后出现了崩溃异常:A java_vm_ext.cc:597] JNI DETECTED ERROR IN APPLICATION: jclass has wrong type: 校验参数后没有任何变化,经过分析验证找到解决方案 二、原因…

Python中的多进程、多线程、协程

Python中的多线程、多进程、协程 一、概述 1. 多线程Thread (threading): 优点:同一个进程中可以启动多个线程,充分利用IO时,cpu进行等待的时间缺点:相对于进程,多线程只能并发执…

Windows:管理用户账户,密码策略和安全配置

在Windows操作系统中,管理用户账户和密码策略是确保系统安全的关键步骤。本文将探讨如何通过PowerShell和其他Windows工具管理用户账户,包括查看和设置密码策略、检查用户状态,以及导出和导入安全策略。这些管理任务对于系统管理员尤其重要&a…

STM32学习和实践笔记(25):USART(通用同步、异步收发器)

一,STM32的USART简介 USART即通用同步、异步收发器,它能够灵活地与外部设备进行全双工数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求。 UART即通用异步收发器,它是在USART基础上裁剪掉了同步通信功能。 开发板上…

Star-CCM+分配零部件至区域2-根据零部件的特性分组分配零部件至区域

前言 前文已经讲解了将零部件分配至区域的方法。其中有一种方法是"将所有部件分配到一个区域"。在工程应用中,有时会把同一种类型的部件分配到一个区域,因此在一个项目中有可能需要多次进行"将所有部件分配到一个区域"。如在电机温…

主机通过带光发端和ops接收端控制屏串口调试记录

场景就是主机电脑使用cutecom通过光纤口再到ops接收端从而控制屏过程 光纤口有个发送端波特率,Ops有接收端波特率,屏有自己的波特率,主机电脑可以通过发串口指令去设置发送端波特率和ops接收端波特率。因为主机只有一个,屏有多种…

【机器学习300问】82、RMSprop梯度下降优化算法的原理是什么?

RMSprop,全称Root Mean Square Propagation,中文名称“均方根传播”算法。让我来举个例子给大家介绍一下它的原理! 一、通过举例来感性认识 建议你第一次看下面的例子时忽略小括号里的内容,在看完本文当你对RMSprop有了一定理解时…

智能助手上线,大模型提供云服务专属顾问

业务背景 在使用云服务的时候,当您遇到复杂问题,如配置、关联或计费方式不明确时,可能需要向客服提交工单进行技术沟通。在漫长的工作过程中,耗费了宝贵的时间和精力。 2024 年 4 月,百度智能云正式推出了融合文心大…

嵌入式学习<1>:建立工程、GPIO和keil仿真

嵌入式学习_part1 本部分笔记用于学习记录,笔记源头 >>b站江科大_STM32入门教程_新建工程 建立工程、GPIO 开发环境:keil MDK、STM32F103C8T6 1 )建立工程 (1)基于寄存器开发、基于标准库 或者 基于HAL库开…

学习网络需要认识的各种设备

网桥(bridge) 网桥工作在数据链路层,可以把多个局域网连接起来,组成一个更大的局域网 以太网中,数据链路层地址就是mac地址,网桥与集线器的区别就是,网桥会过滤mac,只有目的mac地址…

财务管理|基于SprinBoot+vue的财务管理系统(源码+数据库+文档)

财务管理系统 目录 基于SprinBootvue的财务管理系统 一、前言 二、系统设计 三、系统功能设计 系统功能实现 1管理员功能模块 2员工功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍&#xff1…

Word设置代码块格式

前言 Word中无法像Markdown和LaTeX一样插入代码块,若要在Word中插入代码块可以手动设置代码块格式或自动粘贴代码块格式。若不追求完美高亮效果,可使用前者方案;若追求完美的高亮效果,可使用后者方案。下文介绍这2种方案。 手动…

同时安装多个nodejs版本可切换使用,或者用nvm管理、切换nodejs版本(两个详细方法)

目录 一.使用nvm的方法: 1.卸载nodejs 2.前往官网下载nvm 3.安装nvm 4.查看安装是否完成 5.配置路径和淘宝镜像 6.查看和安装各个版本的nodejs 7.nvm的常用命令 二.不使用nvm,安装多个版本: 1.安装不同版本的nodejs 2.解压到你想放…

生信技能45 - 基于docker容器运行生信软件

1. 获取docker镜像 以运行xhmm CNV分析软件为例。 # 搜索仓库镜像 sudo docker search xhmm# 拉取镜像 sudo docker pull ksarathbabu/xhmm_v1.0# 启动镜像,非后台 sudo docker run -it ksarathbabu/xhmm_v1.0 /bin/bash # -i: 交互式操作。 # -t: 终端。 # ksarathbabu/xhmm…