【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
函数定义了一个测试用例,然后使用expect
和toBe
来进行断言。
运行单元测试
运行以下命令来执行测试:
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处理});
});
在这个测试文件中,我们使用了describe
和it
来组织我们的测试代码。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
。这使得测试既快速又独立于外部系统。
通过mockResolvedValue
和mockRejectedValue
,我们可以控制模拟的axios.get
方法在被调用时返回一个成功的Promise或一个失败的Promise,从而测试我们的fetchData
函数在不同情况下的行为。
这种方式非常适合测试依赖于异步数据获取的函数,无需担心网络延迟或服务不可用的问题,同时也能确保测试的准确性和可重复性。
运行测试
总结
通过上述步骤,我们学习了如何在Node.js项目中使用Jest进行单元测试和集成测试。单元测试帮助我们验证各个独立模块的功能,而集成测试确保这些模块能够协同工作。Jest是一个功能强大的测试框架,它提供了丰富的API来编写和运行测试用例。通过这些测试,我们可以提高代码的质量和稳定性。
相关文章:

【Node.js从基础到高级运用】十五、单元测试与集成测试
引言 在Node.js开发过程中,测试是确保代码质量和功能正确性的关键步骤。单元测试和集成测试是最常见的测试类型。下面我们将使用Jest框架来进行测试。 单元测试 单元测试是指对软件中的最小可测试单元进行检查和验证。在Node.js中,这通常指的是函数或者…...
哈工大sse C语言 困难
Q565.(10分数, 语言: C)程序中函数 fun()的功能: 将一个由八进制数字字符组成的字符串转换为与其值相等的十进制整数。规定输入的字符串最多只能包含5位八进制数字字符。 **输入格式要求:gets 提示信息:"输入一个八进制字符串(5位&…...

力扣● 503.下一个更大元素II ● 42. 接雨水
503.下一个更大元素II 与496.下一个更大元素 I的不同是要循环地搜索元素的下一个更大的数。那么主要是对于遍历结束后,单调栈里面剩下的那些元素。 如果直接把两个数组拼接在一起,然后使用单调栈求下一个最大值就可以。 代码实现的话,不用直…...
Java中的包装类
Java中的包装类 一、包装类是什么?二、对应关系:三、举例说明:Integer构造器:包装类特有的机制:自动装箱 自动拆箱常用方法 总结 一、包装类是什么? 以前定义变量,经常使用基本数据类型&#x…...
实时数仓的另一种构建方法starRocks的物化视图
一、 StarRocks是什么 StarRocks是一个分布式的、高性能的OLAP(联机分析处理)数据库,物化视图在StarRocks中具有重要作用。 二、 StarRocks物化视图能干啥 物化视图(Materialized Views)是数据库中的预先计算结果的存储。它们是由一个或多个基础表的聚合数据组成的,这…...
【PHP】通过PHP实时监控Apache、MySQL服务运行状态
一、前言 有些时候我们需要监控一些服务的运行状态,比如说Apach或MySQL的运行状态,最近工作中也开发了这方面的功能,记录下来怎样使用PHP语言来实时监控Apache、MySQL服务的运行状态。 如果想一键开启Apache或MySQL等其他服务可以看这篇文章…...

ETL的全量和增量模式
在当今信息爆炸的时代,数据管理已经成为各行各业必不可少的一环。而在数据管理中,全量与增量模式作为两种主要的策略,各自具有独特的优势和适用场景,巧妙地灵活运用二者不仅能提升数据处理效率,更能保障数据的准确性。…...
常用的IDE推荐
程序员在选择集成开发环境(IDE)时,会考虑多种因素,包括易用性、功能丰富性、性能以及是否支持他们正在使用的编程语言。以下是一些建议的IDE及其优点: 1.JetBrains PyCharm:专为Python开发而设计的IDE。 优…...

6、kubenetes 卷
1、什么是卷 在某些场景下,我们可能希望新的容器可以在之前容器结束的位 置继续运⾏,⽐如在物理机上重启进程。可能不需要(或者不想要) 整个⽂件系统被持久化,但又希望能保存实际数据的⽬录。 Kubernetes通过定义存储…...

前端学习笔记 | Node.js
一、Node.js入门 1、什么是Node.js 定义:是跨平台JS运行环境(可以独立执行JS的环境)作用: 编写数据接口,提供网页资源功能等等前端工程化:为后续学Vue和React等框架做铺垫 2、Node.js为何能执行JSÿ…...

Spark-Scala语言实战(3)
在之前的文章中,我们学习了如何在来如何在IDEA离线和在线安装Scala,想了解的朋友可以查看这篇文章。同时,希望我的文章能帮助到你,如果觉得我的文章写的不错,请留下你宝贵的点赞,谢谢。 Spark-Scala语言实…...

diffusion model(十四): prompt-to-prompt 深度剖析
infopaperPrompt-to-Prompt Image Editing with Cross Attention Controlgithubhttps://github.com/google/prompt-to-promptOrg:Google Research个人复现https://github.com/myhz0606/diffusion_learning个人博客主页http://myhz0606.com/article/p2p 1 前言 基于扩散模型&a…...
线性表的顺序表示(顺序表)
静态分配: #include <stdbool.h> #include <stdio.h>typedef int ElementType;#define MaxSize 50 typedef struct {ElementType data[MaxSize];int length; }SqList;//初始化 //SqList L; void InitList(SqList L) {L.length 0; }//插入 bool ListIn…...
矩阵A的LU分解
文章目录 1. 矩阵的逆矩阵1.1 AB的逆矩阵1.2 转置矩阵 2. 2X2矩阵A消元3. 3X3矩阵A消元4. 运算量5. 置换矩阵-左行右列 本文主要目的是为了通过矩阵乘法实现矩阵A的分解。 1. 矩阵的逆矩阵 1.1 AB的逆矩阵 假设A,B矩阵都可逆 A ( B B − 1 ) A − 1 I (1) A(BB^{-1})A^{-1}…...
深入了解Flutter中Future的全部工厂方法及使用
在Flutter中,Future是一种表示异步操作结果的对象。它代表了一个可能已经完成或尚未完成的计算,可以用来处理异步任务。Flutter提供了多种工厂方法来创建Future对象,每种方法都有其特定的用途和优势。在本文中,我们将深入探讨Flut…...

python的BBS论坛系统flask-django-nodejs-php
为了更好地发挥本系统的技术优势,根据BBS论坛系统的需求,本文尝试以B/S架构设计模式中的django/flask框架,python语言为基础,通过必要的编码处理、BBS论坛系统整体框架、功能服务多样化和有效性的高级经验和技术实现方法ÿ…...

vulnhub-----pWnOS1.0靶机
文章目录 1.信息收集2.漏洞测试3.爆破hash4.提权 首先拿到一台靶机,就需要知道靶机的各种信息(IP地址,开放端口,有哪些目录,什么框架,cms是什么,网页有什么常见的漏洞,如sql注入&…...

vue 消息左右滚动(前后无缝衔接)
演示效果 封装的组件 <!--* Author:* Date: 2024-03-21 19:21:58* LastEditTime: 2024-03-21 20:31:50* LastEditors: Please set LastEditors* Description: 消息左右滚动 --> <template><divid"textScroll"class"text-scroll"mousemove&…...

Qt如何直接处理系统事件(比如鼠标事件),而不是post事件
#include <QtGui/5.15.2/QtGui/qpa/qwindowsysteminterface.h> // 方便调试事件 QWindowSystemInterface::setSynchronousWindowSystemEvents(true); 直接再 qWindowsWndProc函数中处理 通常情况: 事件被放到一个队列中...

Web前端笔记+表单练习+五彩导航
一、笔记 表单:数据交互的一种方式 登录、注册、搜索 <from> <input type""> --- <input type"text"> --- 普通输入框,内容在一行显示 <input type"password"> --- 密码框 <input type"…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...