【Node.js从基础到高级运用】十五、单元测试与集成测试

引言

在Node.js开发过程中,测试是确保代码质量和功能正确性的关键步骤。单元测试和集成测试是最常见的测试类型。下面我们将使用Jest框架来进行测试。

单元测试

单元测试是指对软件中的最小可测试单元进行检查和验证。在Node.js中,这通常指的是函数或者模块。

安装Jest

首先,你需要在你的Node.js项目中安装Jest。通过npm可以轻松安装:

npm install --save-dev jest

配置Jest

package.json文件中添加以下Jest配置:

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

这样,你就可以通过运行npm test命令来执行测试了。

编写单元测试

假设我们有一个简单的函数add,我们想要测试它:

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

为了测试这个函数,我们创建一个测试文件add.test.js

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

在上面的代码中,我们使用test函数定义了一个测试用例,然后使用expecttoBe来进行断言。

运行单元测试

运行以下命令来执行测试:

npm test

Jest将自动找到所有的测试文件并执行它们。
在这里插入图片描述

集成测试

集成测试是指测试应用程序中多个模块或服务协同工作的情况。在Node.js中,这通常涉及到数据库操作、网络请求等。

编写集成测试

假设我们有一个简单的Express服务器,我们想要测试它的一个端点:

// test15.js
const express = require('express');
const add = require('./add');const app = express();app.get('/add', (req, res) => {const { a, b } = req.query;res.send({ result: add(Number(a), Number(b)) });
});module.exports = app;

我们可以使用Jest和supertest来测试这个端点:

npm install --save-dev supertest

创建一个测试文件test15.test.js

// test/test15.test.js
const request = require('supertest'); // 引入supertest库,用于对HTTP请求进行模拟
const app = require('./test15'); // 引入我们的Express应用// 使用describe定义一个测试套件,其中包含了多个测试用例
describe('GET /add', () => {// 使用it定义一个测试用例,测试GET /add端点it('responds with json containing the sum of a and b', (done) => {request(app) // 使用supertest对app发起请求.get('/add') // 指定请求类型为GET,并设置请求路径为/add.query({ a: 1, b: 2 }) // 设置请求查询参数a=1&b=2.expect('Content-Type', /json/) // 预期响应头Content-Type为json类型.expect(200) // 预期响应状态码为200.then(response => { // 请求成功后获取响应对象expect(response.body.result).toBe(3); // 使用expect断言响应体中的result值为3done(); // 调用done回调函数表示测试结束}).catch(err => done(err)); // 捕获异常,如果有异常通过done传递给Jest处理});
});

在这个测试文件中,我们使用了describeit来组织我们的测试代码。describe定义了一个测试套件,它是一系列相关测试用例的集合。it则定义了一个具体的测试用例。

我们通过supertest库来模拟发起HTTP请求,并通过链式调用来设置请求的具体参数和预期的响应。通过.expect方法可以设置对响应的预期,例如预期的响应头和状态码。.then方法用于处理请求成功的情况,我们在其中使用expect来进行断言,验证响应体是否符合预期。

最后,我们使用done回调来告诉Jest这个异步的测试用例何时完成。如果请求过程中出现异常,我们通过.catch捕获异常,并通过done将错误传递给Jest,以便Jest可以正确地标记这个测试用例失败。

运行集成测试

和运行单元测试一样,你只需要执行:

npm test

Jest同样会执行集成测试。
在这里插入图片描述

jest高级运用

我们来实现一个异步函数的测试,该函数从某个API获取数据,并使用mock功能来模拟API调用。这样可以在不实际进行网络请求的情况下测试函数的逻辑。

异步数据获取函数

假设我们有一个函数fetchData,它从一个假设的API https://api.example.com/data 获取数据:

// test15-2.js
const axios = require('axios'); // 引入axios库,用于发起HTTP请求async function fetchData() {const response = await axios.get('https://api.example.com/data'); // 使用axios向API发起GET请求return response.data; // 返回响应体的数据
}module.exports = fetchData;

编写测试并使用Jest Mock

为了测试这个异步函数而不实际发起网络请求,我们将使用Jest的mock功能来模拟axios库。

// test/test15-2.test.js
jest.mock('axios'); // 告诉Jest模拟axios模块
const axios = require('axios'); // 引入axios
const fetchData = require('../test15-2'); // 引入我们的fetchData函数// 定义测试套件
describe('fetchData', () => {// 定义一个测试用例,测试fetchData是否能正确处理数据it('fetches successfully data from an API', async () => {const mockData = { data: 'some data' }; // 定义模拟的API响应数据axios.get.mockResolvedValue(mockData); // 使用mockResolvedValue来模拟axios.get方法的成功返回await expect(fetchData()).resolves.toEqual('some data'); // 使用resolves来测试Promise是否被成功解析,期望fetchData的结果等于'some data'});// 定义另一个测试用例,测试在API请求失败时的行为it('fetches erroneously data from an API', async () => {const errorMessage = 'Network Error'; // 定义模拟的错误消息axios.get.mockRejectedValue(new Error(errorMessage)); // 使用mockRejectedValue来模拟axios.get方法的失败返回await expect(fetchData()).rejects.toThrow(errorMessage); // 使用rejects来测试Promise是否被拒绝,并且抛出了错误消息});
});

在这个高级示例中,我们首先使用jest.mock来告诉Jest我们想要模拟axios模块。这样,当我们在测试中调用axios.get时,实际上调用的是一个Jest提供的模拟函数,而不是真正的axios.get。这使得测试既快速又独立于外部系统。

通过mockResolvedValuemockRejectedValue,我们可以控制模拟的axios.get方法在被调用时返回一个成功的Promise或一个失败的Promise,从而测试我们的fetchData函数在不同情况下的行为。

这种方式非常适合测试依赖于异步数据获取的函数,无需担心网络延迟或服务不可用的问题,同时也能确保测试的准确性和可重复性。

运行测试

在这里插入图片描述

总结

通过上述步骤,我们学习了如何在Node.js项目中使用Jest进行单元测试和集成测试。单元测试帮助我们验证各个独立模块的功能,而集成测试确保这些模块能够协同工作。Jest是一个功能强大的测试框架,它提供了丰富的API来编写和运行测试用例。通过这些测试,我们可以提高代码的质量和稳定性。

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

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

相关文章

安卓面试题多线程 86-90

86. 请列举ThreadPoolexecutor参数配置?corePoolSize- 池中所保存的线程数,包括空闲线程。 maximumPoolSize - 池中允许的最⼤线程数。 keepAliveTime当线程数⼤于核⼼时,此为终⽌前多余的空闲线程等待新任务的最长时间。 unit - keepAliveTime 参数的时间单位。 workQueue …

HarmonyOS开发:超详细介绍如何开源静态共享包,实现远程依赖

前言 当我们开发了一个独立的功能,想让他人进行使用,一般的方式就是开源出去,有源码的方式,也有文件包的形式,当然了也有远程依赖的方式,比如在Android中,我们可以提供源码,也可以打…

SQLiteC/C++接口详细介绍sqlite3_stmt类(一)

返回目录:SQLite—免费开源数据库系列文章目录 上一篇:SQLiteC/C接口详细介绍sqlite3_stmt类简介 下一篇:SQLiteC/C接口详细介绍sqlite3_stmt类(二) ​ 序言: 本文开始了SQLite的第二个类的详细介绍…

Qt 容器类控件

Group Box 使用 QGroupBox 实现一个带有标题的分组框可以把其他的控件放到里面作为一组,这样看起来能更好看一点. 核心属性 属性说明title分组框的标题alignment分组框内部内容的对齐方式flat是否是 “扁平” 模式checkable是否可选择. 设为 true,则在…

2024年华为OD机试真题-石头剪刀布游戏-Java-OD统一考试(C卷)

题目描述: 石头剪刀布游戏有3种出拳形状:石头、剪刀、布。 分别用字母 A,B,C表示。 游戏规则: 1)出拳形状之间的胜负规则如下:A> B;B> C;C> A “>” 左边一个字母,表示相对优势形状。 右边一个字母,表示相对劣势形状。 2) 当本场次中有且仅有一种出拳形状…

鸿蒙Harmony应用开发—ArkTS-高级组件:@ohos.advertising.AdComponent (非全屏广告展示组件))

本模块提供展示非全屏广告的能力。 说明: 本模块首批接口从API Version 11开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 导入模块 import { AdComponent } from ohos.advertising.AdComponent; AdComponent AdComponent(ads: Ar…

webpack5零基础入门-12搭建开发服务器

1.目的 每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化 2.安装相关包 npm install --save-dev webpack-dev-server 3.添加配置 在webpack.config.js中添加devServer相关配置 /**开发服务器 */devServer: {host: localhos…

C# 使用ffmpeg将图片保存为mp4视频

使用 FFmpeg 这个强大的多媒体处理工具,可以轻松地将一系列图片转换为一个 MP4 视频文件。以下是一个基本的命令行示例来完成这个任务: ffmpeg -framerate 25 -i image-%03d.jpg -c:v libx264 -r 30 -pix_fmt yuv420p output.mp4 命令参数说明&#xf…

华为中心AP 配置入侵防御实验

配置入侵防御示例 组网图形 图1 入侵防御组网图 组网需求配置思路操作步骤中心AP的配置文件 组网需求 如图1所示,某企业部署了WLAN网络,内网用户可以访问Internet的Web服务器。现需要在中心AP上配置入侵防御功能,具体要求如下: 保…

接口VS抽象类,我该用哪个?

在Java编程中,接口和抽象类是两个核心概念,它们为面向对象编程提供了强大的支持。理解这两者的区别以及如何正确地使用它们,对于编写高效、可维护的代码至关重要。 接口(Interface) 接口是一种完全抽象的类&#xff…

程序运行时,常见存储区分类及作用

作用栈区(stack) 存放函数的形参和局部变量(auto 类型),由编译器自动分配和释放。生命周期与函数调用相关,函数结束时自动回收。栈区的大小有限,通常较小。例如,函数参数和局部变量。…

Bert的一些理解

Bert的一些理解 Masked Language Model (MLM)Next Sentence Prediction (NSP)总结 参考链接1 参考链接2 BERT 模型的训练数据集通常是以预训练任务的形式来构建的,其中包括两个主要任务:Masked Language Model (MLM) 和 Next Sentence Prediction (NSP)。…

GPT-4与Claude3、Gemini、Sora:AI领域的技术创新与突破

【最新增加Claude3、Gemini、Sora、GPTs讲解及AI领域中的集中大模型的最新技术】 2023年随着OpenAI开发者大会的召开,最重磅更新当属GPTs,多模态API,未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义,不亚…

大模型提示工程和常用的几个场景下Prompt案例

提示工程指南 提示工程(Prompt Engineering)是一门较新的学科,关注提示词开发和优化,帮助用户将大语言模型(Large Language Model, LLM)用于各场景和研究领域。 掌握了提示工程相关技能将有助于用户更好地了…

linux环境部署

war包环境 在Linux系统上部署准备war包环境 查看linux当前版本和系统类型 [rootlocalhost ~]# uname -a Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linuxlinux 打包文件夹 使用tar命令&#xff1…

【PG数据库】CentOS 7 安装 PostgreSQL 14

1 CentOS 7 安装 PostgreSQL 14 1.1下载离线安装包 下载方式:利用离线下载方式在虚拟机中安装PostgreSQL 14 下载链接: https://yum.postgresql.org/14/redhat/rhel-7-x86_64/repoview/postgresqldbserver14.group.html 依次进入下载: 1.…

安卓面试题多线程 66-70

66. 如何避免 Java 线程死锁?要想避免死锁,只需要破坏掉至少一个构造死锁的必要条件即可,而在操作系统中,互斥条件和不可剥夺条件是系统规定的,这也没办法人为更改,而且这两个条件很明显是一个标准的程序应该所具备的特性。所以目前只有请求并持有和环路等待条件是可以被…

24.3 分布式综合应用

24.3 分布式综合应用 1. 分布式事务1.1 分布式事务1.2 分布式事务方案1. 2pc2. 其他方案1.3 Seata分布式事务框架:基于2pc1. 简介2. 启动seata服务1.4 微服务事务案例分析1. 代码分析2. 基于Seata改造2. 分布式锁2.1 简介3. RabbitMQ应用

深度访谈:OpenAI缘何要进军光量子领域

内容来源:量子前哨(ID:Qforepost) 编辑丨王珩 编译/排版丨沛贤 深度好文:2000字丨12分钟阅读 据报道,人工智能巨头最近为其团队增添了一位新成员:Ben Bartlett,他是PsiQuantum的前…

【QT+QGIS跨平台编译】之八十四:【QGIS_Gui跨平台编译】—【错误处理:未实例化QgsMapLayer - QgsHighlight】

文章目录 一、未实例化QgsMapLayer二、错误处理 一、未实例化QgsMapLayer 报错信息: 二、错误处理 第31行修改为: #include "qgsmaplayer.h"