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

一、引言

在进行单元测试时,我们经常会遇到对外部资源的依赖,如数据库、网络接口等。模拟(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.mzph.cn/bicheng/9695.shtml

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

相关文章

iOS面试题链接汇总

iOS开发三年经验 靠这份面试题让我从15k到25k - 简书 2021年,整理的iOS高频面试题及答案(总会有你需要的) - 知乎 iOS面试(内含面试全流程,面试准备工作面试题等)-CSDN博客 runtime: 阿里、字节 一套高效…

Java中静态代理和动态代理设计模式应用实例举例?

静态代理实例 假设我们有一个需求,要记录一个服务接口IService的所有方法调用的开始和结束时间,以此来监控服务的性能。我们可以使用静态代理模式来实现这个需求。 1. 定义服务接口 IService.java: Java 1public interface IService { 2 void serv…

分布式任务调度框架xxl-job使用手册

官网地址和文档地址:https://www.xuxueli.com/xxl-job/ 一、快速入门 1.1 下载源码 https://github.com/xuxueli/xxl-job https://gitee.com/xuxueli0323/xxl-job 下载完成后有以下模块 1.2 初始化数据库 官方指定mysql8.0,但我是mysql5.7 执行/xxl…

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…

Qt 6.7功能介绍

Qt 6.7为我们所有喜欢在构建现代应用程序和用户体验时获得乐趣的人提供了许多大大小小的改进。一些新增内容作为技术预览发布,接下来我们就一起来看看吧: 将C20与Qt一起使用 对于许多编译器工具链来说,C20仍然是可选的和实验性的,…

PVE 脚本工具 pve_source | Pve_Tools

pve_source 安装 wget -q -O /root/pve_source.tar.gz https://bbs.x86pi.cn/file/topic/2023-11-28/file/01ac88d7d2b840cb88c15cb5e19d4305b2.gz && tar zxvf /root/pve_source.tar.gz && /root/./pve_source 脚本加载成功出现使用协议,输入 Y&…

台服dnf局域网搭建,学习用笔记

台服dnf局域网搭建 前置条件虚拟机初始化上传安装脚本以及其他文件至虚拟机密钥publickey.pem客户端配置如果IP地址填写有误,批量修改IP地址 前置条件 安装有vmvarecentos7.6镜像:https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.6.1810/isos/x86…

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

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

Day7 字符串和常用数据结构

文章目录 字符串和常用数据结构使用字符串使用列表生成式和生成器使用元组使用集合使用字典练习练习1:在屏幕上显示跑马灯文字。练习2:设计一个函数产生指定长度的验证码,验证码由大小写字母和数字构成。练习3:设计一个函数返回给…

linux下使用jexus部署aspnet站点

1.运行环境 Centos 7 安装dos2unix工具 yum install dos2unix 安装jexus curl https://jexus.org/release/x64/install.sh|sudo sh2.网站部署 2.1. 将windows下的网站发布包Msc_qingdao_admin.zip上传到linux中, 然后解压后放入/var/www(没有则创建)目录下 r…

福昕PDF阅读器取消手型工具鼠标点击翻页

前言: 本文介绍如何关闭福昕PDF阅读器取消手型工具鼠标点击翻页,因为这样真的很容易误触发PDF翻页,使用起来让人窝火。 引用: NA 正文: 新版的福昕PDF阅读器默认打开了“使用手型工具阅读文章”这个勾选项&#x…

超全MySQL锁机制介绍

前言 MySQL作为关系型数据库管理系统中的佼佼者,为了保证数据的一致性和完整性,在并发控制方面采用了锁机制。锁机制是数据库管理系统用于控制对共享资源的访问,避免多个事务同时修改同一数据造成的数据不一致问题。了解MySQL的锁机制对于数…

python如何使用BlockingScheduler设置钉钉定时自动工作通知?

需求描述 每周五上午11点,通过钉钉工作通知向特定人员推送特定文本内容,文本内容来自数据库计算。 代码 from apscheduler.schedulers.blocking import BlockingScheduler from sqlalchemy import create_engine import requests import pandas as pd…

中信证券:量子产业蓄势待发,看好相关投资机会!

在1994年,数学家彼得肖尔(Peter Shor)首次提出了现在广为人知的肖尔算法,那时许多人认为量子计算机的概念遥不可及、纯属幻想。然而,到了2024年,全球正深入探讨量子科技在现实世界的应用,以及所…

K8S中的弹性云服务如何搭建,可能遇到的问题,如何解决!(稳啦!!!!全都稳啦!!!)

首先我们先来了解一下这玩意儿~~~ 啥是弹性云服务(Elastic Cloud Service)???? 弹性云服务(ECS)是一种基于云计算技术的虚拟服务器,由vCPU、内存、磁盘等组成的获取方便…

pytorch技术栈

张量(Tensors):PyTorch的核心数据结构,用于存储和操作多维数组。 自动微分(Autograd):PyTorch的自动微分引擎,可以自动计算梯度,这对于训练神经网络至关重要。 数据加载…

Git 如何管理标签命令(tag)

1.查看本地仓库tag --1.查看本地仓库tag UserDESKTOP-2NRT2ST MINGW64 /e/GITROOT/STARiBOSS/STARiBOSS-5GCA (gw_frontend_master) $ git tag 1stBossUpgrade V10.0.1_20220224_test V10.0.1_20220301_test tag-gwfrontend-V1.0.12-230625 tag-gw_frontend-23.08.29 tag-gw_f…

45.乐理基础-音符的组合方式-复附点

复附点: 复附点顾名思义就是两个附点 复附点表示的音符,有多少拍?下面拿 复附点四分音符举例,可以把整个音符看成三部分,第一部分是原本的四分音符,第二部分是第一个附点,第三部分是第二个附点&…

ANTLR的学习笔记

ANTLR(Another Tool for Language Recognition)是一款强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛用于构建编程语言、工具和框架。ANTLR由Terence Parr教授开发,是自由和开源的软件&#xff0c…

vue cmd执行报错 ‘vue‘ 不是内部或外部命令

使用vue脚手架快速搭建项目,在cmd中执行:vue init webpack vue-demo,报错: vue 不是内部或外部命令,也不是可运行的程序 或批处理文件。 解决方法,执行如下的命令 npm config list 注意:找到prefix等号后…