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

news2024/11/28 17:42:47

引言

在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值为3
        done(); // 调用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.coloradmin.cn/o/1530121.html

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

相关文章

将html网页展示的图表,下载到PPT文档内,以图片的形式展示在PPT内

使用到的工具有: 开发工具:IDEA 报表开发工具:帆软10.0.19 1、针对帆软报表[普通报表]的设置 1.1首先选中在帆软里制作好的报表,选择模板web属性 1.2.选择数据分析模式,添加一个事件设置,该事件应该设置“…

抖音视频爬虫工具安装|视频无水印批量下载软件

抖音视频批量下载工具安装教程 想要快速、便捷地批量下载抖音视频吗?不用担心,我们为您提供了简单易行的安装教程,让您轻松体验抖音视频的下载乐趣。q1977470120跟随以下步骤,一起来安装抖音视频批量提取工具吧! 步骤…

Android 系统源码中添加可执行程序

Android 系统源码中添加可执行程序 本文基本Android 10的源码环境 android 添加的可执行程序,可以分为两类: * C/C 可执行程序 * Java 可执行程序 (jar)在了解如何给 android 添加可执行程序前,我们需要了解一下ARM…

云原生相关知识

一、kubernetes 1 概述 Kubernetes(也称 k8s 或 “kube”)是一 个​​开源​​的容器编排平台,可以自动完成在部署、管理和扩展容器化应用过程中涉及的许多手动操作。 我们常说的编排的英文单词为 “Orchestration”,它常被解释…

Linux中,黑窗口使用vi编辑文件

linux用的比较少,一般我只用来部署项目的时候安装环境和传文件,好多乱七八糟的命令,好多东西,不会啊啊啊啊啊啊啊。 这个改文件几百年才用一次,我只想编辑一下文件,百度搜出来一大堆命令,各种模式什么的&am…

【JVM】如何判断堆上的对象没有被引用?

如何判断堆上的对象没有被引用? 常见的有两种判断方法:引用计数法和可达性分析法。 引用计数法会为每个对象维护一个引用计数器,当对象被引用时加1,取消引用时减1。 引用计数法的缺点-循环引用 引用计数法的优点是实现简单&…

qt-pdf-viewer-library 编译过程记录

1.qtpdfviewerinitializer.h 中 类模板问题需要修改为下面代码: https://github.com/develtar/qt-pdf-viewer-library 下载代码: 编译出现错误 修改代码,如下: 2.无法触发onViewerLoaded 事件,就是界面无法显示PDF文件 修改下面代码&#…

MySQL 搭建双主复制服务 并 通过 HAProxy 负载均衡

一、MySQL 搭建双主复制高可用服务 在数据库管理中,数据的备份和同步是至关重要的环节,而双主复制(Dual Master Replication)作为一种高可用性和数据同步的解决方案,通过让两个数据库实例同时充当主服务器和从服务器&…

WiFi是可以连接网络,但是在Pixel 手机上就连接提示受阻,无法上网-解决方法

1,通过USB连接手机,然后通过adb命令执行 adb shell settings delete global captive_portal_mode adb shell settings put global captive_portal_mode 0 adb shell settings get global captive_portal_mode adb shell settings delete global capti…

Java 设计模式系列:行为型-状态模式

简介 状态模式(State Pattern)是一种行为型设计模式,允许一个对象在其内部状态改变时改变其行为。状态模式中类的行为是由状态决定的,在不同的状态下有不同的行为。 状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂…

【鸿蒙系统】 ---Harmony 鸿蒙编译构建指导(一)

💌 所属专栏:【鸿蒙系统】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢…

基于Lealfet.js展示Turf.js生成的平滑曲线实践

目录 前言 一、问题的由来 1、创建网页框架 2、创建map对象 3、构建点位,生成路线 二、Turf.js平滑曲线改造 1、官网方法介绍 2、0.4弯曲度曲线 3、0.85弯曲度曲线 4、0.1度弯曲曲线 5、综合对比 总结 前言 在很多的关于路线的gis应用中,我们…

使用甘特图实现高效时间规划

甘特图虽然看似简单,却蕴含着规划时间的奥秘。它将复杂的工序分解成逻辑严密的任务链条,每个短小的条形图块都清晰地道出一个任务的起始、持续和终止。就像指挥家挥舞手中的棒,每个动作都精确拍着节奏,确保各个乐手分工合作、行云流水。择一个好用的甘特图制作工具,会让你事半功…

web前端之不一样的下拉菜单、不选中第一个元素的样式效果、伪类排除第一个元素、符号选择器、hover、not、first、child

MENU 效果图htmlcssJShtmlcss 效果图 htmlcssJS html <nav><ul><li class"navli"><h4>HTML5</h4><ul class"ulson"><li class"lison">HTML5</li></ul></li><li class"na…

论文解读—— 基于边缘梯度方向插值和 Zernike 矩的亚像素边缘检测

论文&#xff1a;《 Subpixel edge detection based on edge gradient directional interpolation and Zernike moment》 地址&#xff1a; http://www.dpi-proceedings.com/index.php/dtcse/article/view/24488 摘要 在本文中&#xff0c;我们提出了一种基于边缘梯度方向插值…

【双指针】算法例题

目录 二、双指针 25. 验证回文数 ① 26. 判断子序列 ① 27. 两数之和II - 输入有序数组 ② 28. 盛最多水的容器 ② 29. 三数之和 ② 二、双指针 25. 验证回文数 ① 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一…

奥特曼剧透GPT-5,将在高级推理功能上实现重大进步

奥特曼&#xff1a;“GPT-5的能力提升幅度将超乎人们的想象...” 自 Claude 3 发布以来&#xff0c;外界对 GPT-5 的期待越来越强。毕竟Claude 3已经全面超越了 GPT-4&#xff0c;成为迄今为止最强大模型。 而且距离 GPT-4 发布已经过去了整整一年时间&#xff0c;2023年3月1…

Nebula Graph-01-Nebula Graph简介和安装以及客户端连接

前言 NoSQL 数据库 图数据库并不是可以克服关系型数据库缺点的唯一替代方案。现在市面上还有很多非关系型数据库的产品&#xff0c;这些产品都可以叫做 NoSQL。NoSQL 一词最早于上世纪 90 年代末提出&#xff0c;可以解释为“非 SQL” 或“不仅是 SQL”&#xff0c;具体解释要…

服务器版本命令查看

1、# uname &#xff0d;a &#xff08;Linux查看版本当前操作系统内核信息&#xff09; 2、# cat /proc/version &#xff08;Linux查看当前操作系统版本信息&#xff09; 3、# cat /etc/issue 或 cat /etc/redhat-release &#xff08;Linux查看版本当前操作系统发行版信息&…

python车辆故障管理系统的设计与实现flask-django-nodejs-php

随着时代的进步&#xff0c;信息科技的不断发展。人类的不断研究、开发&#xff0c;互联网时代已经来临。人们消费的水平也在不断的提高&#xff0c;车辆维修从无到有&#xff0c;慢慢的步入人们的生活&#xff0c;快速的发展&#xff0c;成为新型的消费。网络发展前景无限&…