Jest单元测试:玩转代码的小捉迷藏!

Jest
Jest 是什么?
Jest 是一个流行的 JavaScript 测试框架,专注于简化和改进代码的测试流程。它由 Facebook 开发并维护,具有以下特点:

1、易用性:Jest 提供了一个简单而强大的测试框架,使得编写和运行测试变得非常容易。

2、自动化:它自动发现和运行测试,无需复杂的配置,可立即开始测试代码。

3、断言库:Jest 集成了强大的断言库,用于验证代码的预期行为,帮助您捕获潜在的问题。

4、模拟和模拟函数:Jest 支持模拟测试环境,使得模拟函数和模块变得容易,从而提高了测试的效率。

5、快照测试:Jest 允许您轻松地创建和维护快照测试,以确保 UI 组件的渲染和结构不会意外更改。

6、并发测试:它可以并行运行测试,提高了测试的速度,特别适用于大型代码库。

7、丰富的插件生态系统:Jest 的生态系统中有许多插件和扩展,可以满足各种不同测试需求。

为什么选择 Jest?
Jest 在开发社区中广受欢迎,因为它具备了一切进行前端和后端 JavaScript 测试所需的功能,并且非常易于入门。它不仅用于单元测试,还可用于集成测试和端到端测试。Jest 的自动化特性和强大的功能使得测试变得更加轻松、高效,有助于提高代码质量并减少潜在的问题。无论您是前端开发者还是后端开发者,Jest 都是一个值得考虑的测试工具。

简介
Jest 是一个基于Jasmine和Mocha的测试框架,它提供了一套易于使用的API,可用于编写简洁、可维护的测试用例。Jest还集成了断言库、模拟函数工具和代码覆盖率报告等功能。

安装
首先,确保你已经在项目目录下初始化npm。然后,使用以下命令安装 Jest :

npm install --save-dev jest
  • 1

安装完成后,你可以在package.json中的"scripts"部分添加一个命令,以便更方便地运行测试:

"scripts": {"test": "jest"
}

接下来我们就可以开始愉快的编写测试用例了。

编写测试用例

首先创建一个名为sum.js的文件,其中包含以下函数:

// sum.js
function sum(a, b) {return a + b;
}module.exports = sum;

现在,创建一个名为sum.test.js的文件,以编写针对sum函数的测试用例:

// sum.test.js
const sum = require('./sum');test('adds 1 + 2 to equal 3', () => {expect(sum(1, 2)).toBe(3);
});

在这个测试用例中,我们使用了test全局函数来定义一个测试。其中,第一个参数是测试的描述,第二个参数是一个函数,在这个函数内我们编写测试逻辑。使用expect函数来断言我们的测试结果。

运行测试

现在可以运行测试了。在终端中运行以下命令:

npm test
  • 1

断言

Jest提供了丰富的断言方法,用于验证预期结果。以下是一些常用的断言方法:

expect(value).toBe(expected): 检查value是否等于expected。

expect(value).toEqual(expected): 检查value是否深度等于expected。

expect(value).toBeNull(): 检查value是否为null。

expect(value).toBeDefined(): 检查value是否已定义。

expect(value).toBeTruthy(): 检查value是否为真值。

expect(value).toBeFalsy(): 检查value是否为假值。

expect(value).not.toBe(expected): 检查value是否不等于expected。

异步测试
在处理异步逻辑时,Jest提供了多种方法来编写和处理异步测试。
常用的有两种方式:

使用async和await关键字:

test('async test', async () => {const data = await fetchData();expect(data).toEqual(expectedData);
});

使用done参数:

test('callback test', (done) => {fetchData((data) => {expect(data).toEqual(expectedData);done();});
});

Mocking

在测试中,我们经常会需要模拟函数或模块的行为。Jest提供了内置的模拟函数工具来实现此功能。

以下是一个使用Jest的模拟函数的示例:

function fetchData(callback) {// 假设这是一个异步操作setTimeout(() => {callback('Hello Jest!');}, 1000);
}test('mocking test', () => {const mockCallback = jest.fn();fetchData(mockCallback);expect(mockCallback).toHaveBeenCalledTimes(1);expect(mockCallback).toHaveBeenCalledWith('Hello Jest!');
});

在上面的示例中,我们使用jest.fn()创建一个模拟函数mockCallback,然后将其作为回调函数传递给fetchData函数。通过使用jest.fn(),我们可以跟踪这个模拟函数的调用次数和传入的参数,以进行断言。

代码覆盖率
代码覆盖率是衡量测试覆盖范围的指标。Jest提供了内置的代码覆盖率工具,可以帮助你分析测试覆盖情况。

通过在package.json中添加以下配置,可以生成代码覆盖率报告:

"scripts": {"test": "jest --coverage"
}

运行npm test命令后,Jest将会生成一个代码覆盖率报告,展示你的测试覆盖情况。

高级配置

Jest提供了丰富的配置选项,用于满足项目的需求。你可以在项目根目录下创建一个jest.config.js文件来配置Jest。

以下是一个简单的配置示例:

// jest.config.js
module.exports = {verbose: true,testEnvironment: 'node',coverageDirectory: 'coverage',collectCoverageFrom: ['src/**/*.js'],
};

异常测试

在测试代码中,我们需要确保正确地处理异常情况。Jest提供了多个断言方法来处理异常。

function divide(a, b) {if (b === 0) {throw new Error('Divide by zero');}return a / b;
}test('divide should throw an error when dividing by zero', () => {expect(() => {divide(10, 0);}).toThrow('Divide by zero');
});

在上面的示例中,我们使用toThrow断言方法来验证代码是否会抛出预期的错误。

测试异步代码的错误

当测试异步代码时,必须确保能够捕捉到异步操作中的错误。Jest提供了几种方式来处理这种情况。

async function fetchData() {return new Promise((resolve, reject) => {setTimeout(() => {reject('Fetch error');}, 1000);});
}test('fetchData should throw an error', async () => {expect.assertions(1);try {await fetchData();} catch (error) {expect(error).toEqual('Fetch error');}
});

在上面的示例中,我们使用expect.assertions来确保至少有一个断言被执行。然后使用try-catch块捕捉到fetchData函数中的错误,并使用断言验证错误的值。

测试对象的方法调用次数
有时候我们需要确保对象的方法被正确调用了指定的次数。Jest提供了用于检查模拟函数调用次数的方法。

class Counter {constructor() {this.count = 0;}increment() {this.count++;}
}test('Counter increment method should be called twice', () => {const counter = new Counter();counter.increment();counter.increment();const incrementMock = jest.spyOn(counter, 'increment');expect(incrementMock).toHaveBeenCalledTimes(2);
});

在上面的示例中,我们使用jest.spyOn来监视Counter类的increment方法,然后通过调用两次increment方法,并使用toHaveBeenCalledTimes断言方法验证方法被正确调用了两次。

测试组件交互
在测试React组件时,我们通常需要模拟用户交互和验证组件的行为。Jest提供了一些方法和工具来帮助测试React组件。

import { render, fireEvent } from '@testing-library/react';
import Button from './Button';test('Button click should trigger callback', () => {const handleClick = jest.fn();const { getByText } = render(<Button onClick={handleClick}>Click me</Button>);const button = getByText('Click me');fireEvent.click(button);expect(handleClick).toHaveBeenCalled();
});

在上面的示例中,我们使用@testing-library/react库中的render函数和fireEvent工具来渲染和测试组件。然后使用jest.fn创建一个模拟函数来监视回调函数的调用,并通过模拟点击按钮来触发回调,并使用toHaveBeenCalled断言方法来验证回调函数是否被调用。

快照测试
快照测试是一种用于捕捉组件或数据结构的初始渲染和状态的测试方法。Jest的toMatchSnapshot方法可以用来创建和比较快照。

import renderer from 'react-test-renderer';
import MyComponent from './MyComponent';test('MyComponent snapshot', () => {const tree = renderer.create(<MyComponent />).toJSON();expect(tree).toMatchSnapshot();
});

在第一次运行测试时,Jest将创建一个快照文件,然后在后续运行时将快照与新的渲染结果进行比较。这有助于检测组件是否发生了意外更改。

参数化测试

有时我们需要测试一组相似的输入,可以使用参数化测试来减少代码重复。

const testData = [{ input: 2, expected: 4 },{ input: 3, expected: 9 },{ input: 4, expected: 16 },
];test.each(testData)('square(%i) should return %i', (input, expected) => {expect(square(input)).toBe(expected);
});

在上面的示例中,我们使用test.each方法来定义一个参数化测试,它会根据不同的输入值多次运行相同的测试代码,从而避免了重复的测试用例。

自定义匹配器

Jest允许你创建自定义匹配器,以便更容易地编写特定于应用程序的断言。

expect.extend({toBeValidEmail(received) {const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$/i;const pass = regex.test(received);if (pass) {return {message: () => `expected ${received} not to be a valid email`,pass: true,};} else {return {message: () => `expected ${received} to be a valid email`,pass: false,};}},
});test('email validation', () => {expect('test@example.com').toBeValidEmail();expect('invalid-email').not.toBeValidEmail();
});

在上面的示例中,我们创建了一个自定义匹配器toBeValidEmail,用于验证字符串是否为有效的电子邮件地址。这使得我们可以使用自定义的断言来验证应用程序的特定行为。

使用beforeEach和afterEach
beforeEach和afterEach函数允许你在每个测试用例之前和之后执行特定的操作,例如设置和清理测试环境。

let counter = 0;beforeEach(() => {counter++;
});afterEach(() => {counter = 0;
});test('increment counter', () => {expect(counter).toBe(1);
});test('reset counter', () => {expect(counter).toBe(1);counter = 5;expect(counter).toBe(5);
});

在上面的示例中,beforeEach用于在每个测试用例之前递增counter,而afterEach用于在每个测试用例之后将counter重置为0,以确保测试的隔离性。

测试组件的生命周期方法
如果你使用 React 或其他支持生命周期方法的库,你可以使用 jest 和 enzyme(或其他库)来测试组件的生命周期方法。

import React from 'react';
import { mount } from 'enzyme';
import MyComponent from './MyComponent';test('componentDidMount is called', () => {const componentDidMountSpy = jest.spyOn(MyComponent.prototype, 'componentDidMount');const wrapper = mount(<MyComponent />);expect(componentDidMountSpy).toHaveBeenCalled();componentDidMountSpy.mockRestore();
});

在上面的示例中,我们使用 enzyme 来挂载一个 React 组件,并使用 jest.spyOn 来监视 componentDidMount 生命周期方法的调用。

模拟时间
有时候需要测试与时间相关的操作,比如 setTimeout 或 setInterval。Jest 提供了一种模拟时间的方式。

jest.useFakeTimers();test('setTimeout test', () => {const callback = jest.fn();setTimeout(callback, 1000);jest.advanceTimersByTime(1000);expect(callback).toHaveBeenCalled();
});

在这个示例中,我们使用 jest.useFakeTimers() 来模拟时间,并使用 jest.advanceTimersByTime 来快进时间以触发 setTimeout 回调函数。

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助

  视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。   

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

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

相关文章

uniapp h5 发行后 微信第二次打开网址 页面白屏

发行后把网址给客户&#xff0c;第一次可以正常登录打开&#xff0c;第二次打开白屏 原因&#xff1a;第一次打开时没有token&#xff0c;所以跳转登录页&#xff0c;可以正常访问 第二次打开时有token&#xff0c;但是网址根目录没有配置默认页面&#xff0c;所以白屏 解决…

Windows Server调整策略实现999999个远程用户用时登录

正文共&#xff1a;1234 字 23 图&#xff0c;预估阅读时间&#xff1a;2 分钟 上篇文章中&#xff08;Windows Server 2019配置多用户远程桌面登录服务器&#xff09;&#xff0c;我们主要介绍了Windows Server 2019在配置远程桌面时&#xff0c;如何通过3种方式创建本地用户账…

使用Qt连接scrcpy-server控制手机

Qt连接scrcpy-server 测试环境如何启动scrcpy-server1. 连接设备2. 推送scrcpy-server到手机上3. 建立Adb隧道连接4. 启动服务5. 关闭服务 使用QTcpServer与scrcpy-server建立连接建立连接并视频推流完整流程1. 开启视频推流过程2. 关闭视频推流过程 视频流的解码1. 数据包协议…

NVMe系统内存结构 - Meta Data

NVMe系统内存结构 - Meta Data 1 为什么需要数据保护2 Meta Data定义3 Meta Data传输方式4 常见Meta Data使用场景4.1 不带数据保护信息4.2 带数据保护信息“数据写”流程4.3 带数据保护信息“数据读”流程4.4 SSD内部加入数据保护信息4.5 SSD内部根据数据保护信息验证数据 本文…

如何在你的网站接入QQ登录?

文章目录 准备阶段申请QQ登录的权限创建应用最后上传qqlogin.php代码 准备阶段 国内服务器和备案域名需要你有张独一无二本人的身份证你正面手持身份证的图片一张100px*100px的网站图标 申请QQ登录的权限 首先访问qq互联&#xff0c;点击我直接访问 登陆完成后我们点击面的…

bash shell基础命令(一)

1.shell启动 shell提供了对Linux系统的交互式访问&#xff0c;通常在用户登录终端时启动。系统启动的shell程序取决于用户账户的配置。 /etc/passwd/文件包含了所有用户的基本信息配置&#xff0c; $ cat /etc/passwd root:x:0:0:root:/root:/bin/bash ...例如上述root账户信…

Python新年文字烟花简单代码

简单的Python新年烟花代码示例&#xff1a; import random import timedef create_firework():colors [红色, 橙色, 黄色, 绿色, 蓝色, 紫色]flashes [爆裂, 闪光, 旋转, 流星, 喷射]color random.choice(colors)flash random.choice(flashes)print(f"发射一枚{color…

redis之单线程和多线程

目录 1、redis的发展史 2、redis为什么选择单线程&#xff1f; 3、主线程和Io线程是怎么协作完成请求处理的&#xff1f; 4、IO多路复用 5、开启redis多线程 1、redis的发展史 Redis4.0之前是用的单线程&#xff0c;4.0以后逐渐支持多线程 Redis4.0之前一直采用单线程的主…

GUI编程(函数解析以及使用)

1.介绍 AWT&#xff08;Abstract Window Toolkit&#xff09;和Swing 是 Java 提供的用于创建图形用户界面&#xff08;GUI&#xff09;的类库。 AWT&#xff1a;AWT 是 Java 最早提供的 GUI 类库&#xff0c;它基于本地平台的窗口系统&#xff0c;使用操作系统的原生组件进行…

文件的创建时间可以修改吗,怎么改?

文件的创建时间可以修改吗&#xff0c;怎么改&#xff1f;文件的创建时间是由操作系统自动生成并记录的&#xff0c;通常情况下无法直接修改。创建时间是文件的属性之一&#xff0c;它反映了文件在文件系统中的生成时间。一旦文件被创建&#xff0c;其创建时间就被确定下来&…

Vulnhub-tr0ll-1

一、信息收集 端口收集 PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.2 | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_-rwxrwxrwx 1 1000 0 8068 Aug 09 2014 lol.pcap [NSE: writeable] | ftp-syst: | STAT: | FTP …

分布式搜索——Elasticsearch

Elasticsearch 文章目录 Elasticsearch简介ELK技术栈Elasticsearch和Lucene 倒排索引正向索引倒排索引正向和倒排 ES概念文档和字段索引和映射Mysql与Elasticsearch 安装ES、Kibana安装单点ES创建网络拉取镜像运行 部署kibana拉取镜像部署 安装Ik插件扩展词词典停用词词典 索引…

Linux 内核大转变:是否将迈入现代 C++ 的时代?

Linux开发者 H. Peter Anvin 在邮件列表中重启了关于 Linux内核C代码转换为C的讨论&#xff0c;并陈述了自己的观点。说之前先看一下这个话题的历史背景。 早在2018年4月1日&#xff0c;Andrew Pinski提议将 Linux 内核源码转为 C&#xff0c;在文中写道之所以引入是由于以下优…

centos7配置时间同步网络时间

centos7配置时间同步网络时间 1、安装 NTP 工具。 sudo yum install -y ntp2启动 NTP 服务。 sudo systemctl start ntpd3、将 NTP 服务设置为开机自启动。 sudo systemctl enable ntpd4、验证 date

Xmind 网页端登录及多端同步

好久没用 Xmind 了&#xff0c;前几天登录网页端突然发现没办法登录了&#xff0c;总是跳转到 Xmind AI 页面。本以为他们不再支持网页端了&#xff0c;后来看提示才知道只是迁移到了新的网址&#xff0c;由原来的 xmind.works 现在改成了的 xmind.ai。又花费好长时间才重新登录…

JAVAEE——request对象(三)

1. request对象 1.1 知识点 &#xff08;1&#xff09;乱码问题的两种解决方式 &#xff08;2&#xff09;post和get提交的区别 &#xff08;3&#xff09;request接收同名参数的问题 1.2 具体内容 使用request接收参数 <%page contentType"text/html; charsetut…

探索2023年大模型与AIGC峰会:程序员的学习之旅与未来展望

在2023年的技术前沿&#xff0c;大模型与AIGC峰会无疑是一个备受瞩目的盛会。 作为程序员&#xff0c;你将从这次大会中学到什么&#xff1f;这次峰会将为你揭示哪些前沿科技趋势&#xff1f;让我们一起来探讨这个问题。 一、理解大模型与AIGC 大模型和AIGC是人工智能领域中两…

离线数据仓库-关于增量和全量

数据同步策略 数据仓库同步策略概述一、数据的全量同步二、数据的增量同步三、数据同步策略的选择 数据仓库同步策略概述 应用系统所产生的业务数据是数据仓库的重要数据来源&#xff0c;我们需要每日定时从业务数据库中抽取数据&#xff0c;传输到数据仓库中&#xff0c;之后…

x-cmd pkg | mermaid - 流程图、时序图等图表绘制工具

简介 mermaid-cli 是由 Mermaid 官方提供的命令行工具&#xff0c;用于将 Mermaid 语法的文本转换为 SVG / PNG / PDF。 Mermaid 是一个基于 JavaScript 的图表绘制工具&#xff0c;它使用简单的文本描述语法&#xff0c;就可以绘制出流程图、时序图、甘特图等多种图表。 首次…

C++标准学习--智能指针

shared_ptr和weak_ptr的配合使用是个问题。unique_ptr的使用场合似乎比较局限。 文章C 智能指针详解&#xff08;一&#xff09;——unique_ptr - 知乎 (zhihu.com) 介绍了unique_ptr的使用。它可以由shared_ptr转来&#xff0c;主要用到了std::move。 主要场景其中提到&#…