NodeJs如何做API接口单元测试? --【elpis全栈项目】
NodeJs API接口单元测试
api单元测试需要用到的
assert
:断言库 (还要一些断言库比如:Chai
)supertest
: 模拟http请求
简单的例子:
const express = require('express');
const supertest = require('supertest');
const assert = require('assert');// 创建一个 Express 应用
const app = express();
app.get('/api/user', (req, res) => {res.status(200).json({ name: 'John Doe' });
});// 测试用例
describe('GET /api/user', () => {it('应该返回用户信息', async () => {const request = supertest(app)const res = await request().get('/api/user') // 发送 GET 请求.set('Accept', 'application/json') // 设置请求头.expect('Content-Type', /json/) // 验证响应头.expect(200); // 验证状态码// 验证响应体assert.strictEqual(res.body.name, 'John Doe');});
});
一、 断言
- Node.js 有内置的断言模块
assert
,用于在代码中验证某些条件是否为真。如果条件不满足,assert 会抛出一个 AssertionError,导致测试失败。
简单介绍一些NodeJs内置的断言assert的一些属性方法:assert.ok(value[, message])
可以直接简写为assert()
验证value 是否为真assert.ok(1);
// 通过assert.ok(0, '值不能为 0');
// 抛出 AssertionError,错误信息为 “值不能为 0”
assert.strictEqual(actual, expected[, message])
验证是否 严格相等(===)assert.strictEqual(1, 1)
; // 通过
assert.notStrictEqual(actual, expected[, message])
验证是否 不严格相等(!==)assert.deepStrictEqual(actual, expected[, message])
验证是否 深度严格相等(适用于对象或数组)assert.deepStrictEqual({ a: 1 }, { a: '1' })
; // 抛出 AssertionError,因为类型不同
assert.notDeepStrictEqual(actual, expected[, message])
验证是否 深度不严格相等(上面的例子不会抛错)assert.equal(actual, expected[, message])
验证是否 相等(==,非严格相等)。assert.notEqual(actual, expected[, message])
验证是否不相等(!=,非严格相等)。assert.throws(block[, error][, message])
验证 block 函数是否会 抛出错误。
assert.throws(() => {throw new Error('错误信息');},Error, // 验证错误类型'未抛出预期错误' // 自定义错误信息 );
assert.doesNotThrow(block[, error][, message])
验证 block 函数是否 不会抛出错误。assert.fail([message])
强制抛出一个 AssertionError,标记测试失败assert.fail('测试失败')
- 总之: assert 是 Node.js 内置的断言模块,适合简单的测试场景。如果需要更丰富的功能和更友好的语法,可以考虑使用 chai 等第三方断言库。
- 还有一些第三方库,比如
chai
,它支持多种风格的断言。Chai
是一个可以在node和浏览器环境运行的BDD/TDD
断言库,可以和任何JavaScript测试框架结合。
按使用风格:
assert
风格:类似于 Node.js 内置的 assert,但功能更强大。expect
风格:链式语法,可读性更高。should
风格:基于原型链的语法,适合 BDD(行为驱动开发)。
// assert 风格
assert(res.body.success === true)// expect 风格
expect(1 + 1).to.equal(2);
expect({ a: 1 }).to.deep.equal({ a: 1 });// should 风格
chai.should();
(1 + 1).should.equal(2);
按测试风格:
-
BDD
(Behavior Driven Development行为驱动开发):是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作(做正确的事
) -
TDD
(Test-Driven Development测试驱动开发): 测试先于编写代码的思想用于指导软件开发(正确的做事
)expect和should是BDD风格的。两者使用相同的语言链
- expect使用构造函数来创建断言对象实例
- should使用Object.prototype提供一个getter方法来实现,不兼容IE
assert属于TDD
- 除语法糖外,assert和node.js的非常相似,assert是三种断言风格唯一不支持链式调用的
chai详细介绍:学习Chai断言库
二、 supertest, 用于测试 HTTP 服务的库
supertest
是一个用于测试 HTTP 服务的 Node.js 库,特别适合测试 Express 或其他基于 Node.js 的 Web 服务器。它提供了简洁的 API 来构造和发送 HTTP 请求,并验证响应结果。supertest 通常与测试框架(如 Mocha、Jest 等)结合使用,用于编写端到端(E2E)测试或集成测试。
...
// 测试用例
describe('GET /api/user', () => {it('应该返回用户信息', async () => {const request = supertest(app)const res = await request().get('/api/user') // 发送 GET 请求.set('Accept', 'application/json') // 设置请求头.expect('Content-Type', /json/) // expect属于supertest内置断言,验证响应头.expect(200); // supertest内置断言,验证状态码});
});
...
下面列举一些supertest属性方法:
- 构造请求
.get(url)
:发送 GET 请求。.post(url)
:发送 POST 请求。.put(url)
:发送 PUT 请求。.delete(url)
:发送 DELETE 请求。.patch(url)
:发送 PATCH 请求。.head(url)
:发送 HEAD 请求。
- 设置请求头,
.set(field, value)
例如:.set('Authorization', 'Bearer token')
// 设置 Authorization 头.set('Accept', 'application/json')
; // 设置 Accept 头
- 发送请求体,使用
.send(data)
方法可以发送请求体,适用于 POST、PUT 等请求。.send({ name: 'John', age: 30 })
- 设置查询参数, 使用
.query(params)
方法可以设置查询参数。.query({ page: 1, limit: 10 })
; // 设置查询参数 ?page=1&limit=10
- 设置请求类型, 使用
.type(type)
方法可以设置请求的Content-Type
。.type('json')
// 设置 Content-Type 为 application/json.type('form')
// 设置 Content-Type 为 application/x-www-form-urlencoded.type('text')
// 设置 Content-Type 为 text/plain
- 文件上传, 使用
.attach(field, file)
方法可以上传文件。.attach('file', 'path/to/file.txt')
; // 上传文件
- 验证响应, 内置了
.expect(...)
方法,与第三方断言库库chai
的expect作用类似,只是supertest的内置方法更专注于 HTTP 响应的验证, 而 chai 的 expect 是一个通用的断言库,适用于更广泛的场景。.expect(status)
:验证状态码。.expect(header, value)
:验证响应头。.expect(body)
:验证响应体。.expect(function(res) { ... })
:自定义验证逻辑。
- 处理响应,使用 .end(callback) 方法可以处理响应结果。
.get('/api/data').end((err, res) => { if (err) throw err; ...})
- 超时设置, 使用
.timeout(ms)
方法可以设置请求的超时时间。 - 重定向, 使用
.redirects(n)
方法可以设置最大重定向次数。.redirects(2)
// 最多允许 2 次重定向
- Cookie, 使用
.set('Cookie', cookie)
方法可以设置请求的 Cookie。 - 自定义 Agent, 使用
.agent()
方法可以创建一个自定义的 superagent 实例,用于保持会话
const agent = request.agent(app);agent.post('/api/login').send({ username: 'john', password: '123456' }).end((err, res) => {if (err) throw err;agent.get('/api/data').end((err, res) => {if (err) throw err;console.log(res.body);});});
- 响应对象属性, 在
.end()
或.expect()
的回调函数中,可以访问响应对象的属性。
.end((err, res) => {if (err) throw err;console.log(res.status); // 状态码console.log(res.headers['content-type']); // 响应头console.log(res.body); // 响应体console.log( res.text); // 原始响应文本。});
三、完整配置
我在项目中的配置:(也不全,简单参考一下)
const assert = require('assert');
const supertest = require('supertest');
const md5 = require('md5');
const elpisCore = require('../../elpis-core')const signKey = '620b048b-8ac3-431b-845d-bcaf63ecc738'
const st = Date.now();describe('测试 project 相关接口', function () {this.timeout(60000);let request;it('启动服务', async () => {const app = await elpisCore.start();request = supertest(app.listen());});it('GET /api/project/model_list', async () => {let tmpRequest = request.get('/api/project/model_list');tmpRequest = tmpRequest.set('s_t', st);tmpRequest = tmpRequest.set('s_sign', md5(`${signKey}_${st}`))const res = await tmpRequest;assert(res.body.success === true)const resData = res.body.data;assert(resData.length > 0);for (let i = 0; i < resData.length; i++) {const item = resData[i];assert(item.model);assert(item.model.key);assert(item.model.name);assert(item.project);for (const projKey in item.project) {assert(item.project[projKey].key);assert(item.project[projKey].name);}}});})
相关文章:
NodeJs如何做API接口单元测试? --【elpis全栈项目】
NodeJs API接口单元测试 api单元测试需要用到的 assert:断言库 (还要一些断言库比如:Chai)supertest: 模拟http请求 简单的例子: const express require(express); const supertest require(supertest); const assert require(assert);…...
bundletool来特定设备规范的json安装aab包
1、获取自己设备的设备规范json java -jar ./bundletool.jar get-device-spec --outputj:/device-spec.json 2、根据设备规范生成apks包 java -jar ./bundletool.jar build-apks --device-specj:/device-spec.json --bundleapp-dev-release.aab --output随便的文件名.apks -…...

2024年第十五届蓝桥杯青少组国赛(c++)真题—快速分解质因数
快速分解质因数 完整题目和在线测评可点击下方链接前往: 快速分解质因数_C_少儿编程题库学习中心-嗨信奥https://www.hixinao.com/tiku/cpp/show-3781.htmlhttps://www.hixinao.com/tiku/cpp/show-3781.html 若如其他赛事真题可自行前往题库中心查找,题…...

.Net Core微服务入门全纪录(四)——Ocelot-API网关(上)
系列文章目录 1、.Net Core微服务入门系列(一)——项目搭建 2、.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上) 3、.Net Core微服务入门全纪录(三)——Consul-服务注…...

chrome游览器JSON Formatter插件无效问题排查,FastJsonHttpMessageConverter导致Content-Type返回不正确
问题描述 chrome游览器又一款JSON插件叫JSON Formatter,游览器GET请求调用接口时,如果返回的数据是json格式,则会自动格式化展示,类似这样: 但是今天突然发现怎么也格式化不了,打开一个json文件倒是可以格…...

[Qt]系统相关-网络编程-TCP、UDP、HTTP协议
目录 前言 一、UDP网络编程 1.Qt项目文件 2.UDP类 QUdpSocket QNetworkDatagram 3.UDP回显服务器案例 细节 服务器设计 客户端设计 二、TCP网络编程 1.TCP类 QTcpServer QTcpSocket 2.TCP回显服务器案例 细节 服务器设计 客户端设计 三、HTTP客户端 1.HTTP…...

docker 安装 nginx 详解
在平常的开发工作中,我们经常会用到 nginx,那么在 docker 中 如何安装 nginx呢?又有哪些需要注意的事项呢?简单来说,第一步:拉取 nginx 镜像;第二步:创建 挂载目录并设置 nginx.conf…...

2025年大模型气象预测架构与商业化影响
随着人工智能技术,尤其是大模型(如深度学习、大规模神经网络)的飞速发展,气象预测的传统方法正在经历深刻变革。2025年,气象预测将借助大模型技术进入一个新的阶段。本文将从架构角度详细探讨2025年大模型在气象预测中的应用,并分析其对商业化的潜在影响。 一、2025年大模…...

基于51单片机和ESP8266(01S)、八位数码管、独立按键的WiFi定时器时钟
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、延时函数2、定时器03、串口4、数码管扫描5、独立按键扫描 四、主函数总结 系列文章目录 前言 有三个版本: ①普中开发板版本1:28800bps11.0592MHz,12T ②普中开发板版本2&am…...
Androidstudio 中,project下的.gitignore和module下的.gitignore有什么区别,生效优先级是什么
在 Android Studio 项目中,project 根目录下的 .gitignore 文件和 module 目录下的 .gitignore 文件作用和生效优先级是不同的,理解它们之间的区别非常重要,可以避免不必要的提交和冲突。 1. project 根目录下的 .gitignore: 作…...

python学习笔记3-字符串常用的方法
一、判断(9个): 二、查找和替换(8个) 三、⼤⼩写转换(5个) 四、⽂本对⻬(3个) 五、去除空⽩字符(3个) 六、拆分和连接 (6个࿰…...

提示词工程(Prompt Engineering)
1. Prompt 是什么? Prompt:提示词,是描述 AI 需要执行的任务的自然语言文本。 如上图所示,Prompt就是用户的提问。其实我们大家都用过Prompt,比如我们使用的ChatGPT、文心一言、豆包等AI产品时的提问就是Prompt&…...

后端开发Web
Maven Maven是apache旗下的一个开源项目,是一款用于管理和构建java项目的工具 Maven的作用 依赖管理 方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题 统一项目结构 提供标准、统一的项目结构 项目构建 标准跨平台(…...

set和map(二)详解
文章目录 mapoperator[ ]的底层operator[ ]使用的实例 multimapequal_range 两道题目题目解析算法原理代码题目解析算法原理代码 map map和set大部分都相似,只有insert插入键值对不同,insert要插入pair,pair中有key和value。erase和find只与key有关&…...
第4章:Python TDD消除重复与降低依赖实践
写在前面 这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许…...

【语言处理和机器学习】概述篇(基础小白入门篇)
前言 自学笔记,分享给语言学/语言教育学方向的,但对语言数据处理感兴趣但是尚未入门,却需要在论文中用到的小伙伴,欢迎大佬们补充或绕道。ps:本文不涉及公式讲解(文科生小白友好体质)ÿ…...

vue3+uniapp开发鸿蒙初体验
去年7月20号,uniapp官网就已经开始支持鸿蒙应用开发了,话不多说,按照现有规则进行配置实现一下鸿蒙开发效果; 本文基于macOS Monterey 版本 12.6.5实现 开发鸿蒙的前置准备 这里就直接说我的版本: DevEco Studio 5.…...

Android四种方式刷新View
Android四种方式刷新View 1.前言: 最近在切换主题时有个TextView是Gone的状态,切换主题后内容没有显示,于是排查代码,刚开始以为是textView没有设置内容,但是打印日志和排查发现有setText. 2.View.VISIBLE与View.GO…...

【数学建模美赛速成系列】O奖论文绘图复现代码
文章目录 引言折线图 带误差棒得折线图单个带误差棒得折线图立体饼图完整复现代码 引言 美赛的绘图是非常重要得,这篇文章给大家分享我自己复现2024年美赛O奖优秀论文得代码,基于Matalab来实现,可以直接运行出图。 折线图 % MATLAB 官方整理…...

【27】Word:徐雅雯-艺术史文章❗
目录 题目 NO1.2 NO3 NO4 NO5 NO6.7 NO8.9 NO10.11 注意:修改样式的字体颜色/字号,若中英文一致,选择所有脚本。格式相似的文本→检查多选/漏选格式刷F4重复上一步操作请❗每一步检查和保存 题目 NO1.2 F12另存为布局→行号布局…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...