JS 中怎么用 Jest 对包含 fetch 和 WebSocket 的异步模块进行单元测试

秋丽同学_6115

秋丽同学_6115

2026-11-06

435人浏览

原创

Jest 测试含 fetch 和 WebSocket 的异步模块需隔离依赖、控制异步流、模拟响应:mock fetch 返回 Response,mock WebSocket 并触发事件,每次测试后清理 mock,组合测试时按序模拟依赖并验证状态流转与错误处理。

js 中怎么用 jest 对包含 fetch 和 websocket 的异步模块进行单元测试

用 Jest 测试含 fetch 和 WebSocket 的异步模块,核心是**隔离外部依赖、控制异步流、模拟响应行为**。Jest 自带的 jest.mock() 和 mockImplementation() 能覆盖大部分场景,无需额外库(如 msw 或 websocket-mock)也能完成可靠测试。

模拟 fetch 请求(替代原生 window.fetch)

Jest 默认会自动 mock 全局 fetch,但需手动配置返回值。关键是:确保被测函数实际调用的是 mock 版本,并能验证请求参数与响应逻辑。

  • 在测试前用 global.fetch = jest.fn() 显式 mock(尤其在非浏览器环境如 Node 中)
  • 用 mockResolvedValue 返回 Promise 包裹的 Response 对象,注意构造合法的 Response(可用 new Response(body, options))
  • 验证请求是否按预期发起:expect(fetch).toHaveBeenCalledWith(url, config)

示例:

test('fetches user data', async () => {
  const mockData = { id: 1, name: 'Alice' };
  global.fetch.mockResolvedValue(new Response(JSON.stringify(mockData), { status: 200 }));

  const result = await getUser(1); // 假设这是被测函数

  expect(fetch).toHaveBeenCalledWith('https://api.example.com/users/1');
  expect(result).toEqual(mockData);
});

模拟 WebSocket 行为(拦截 new WebSocket 构造与事件触发)

WebSocket 是事件驱动对象,不能只 mock 构造函数,还需模拟其 onopen、onmessage 等回调触发时机。常用做法是:mock WebSocket 构造函数,返回一个带可控事件触发能力的假实例。

  • 用 jest.mock('ws')(Node)或 global.WebSocket = jest.fn()(浏览器环境)拦截构造调用
  • 让 mock 实例保存传入的 onmessage 等 handler,并提供 triggerMessage(data) 方法主动调用它们
  • 在测试中等待消息处理完成(配合 await waitFor(() => expect(...).toBe(...)) 或 Promise + resolve)

示例(简化版 mock):

Expanso yaml-to-json
Expanso yaml-to-json

使用 Expanso Edge 管道将 YAML 输入转换为 JSON 格式。

下载
class MockWebSocket {
  constructor(url) {
    this.url = url;
    this.onopen = null;
    this.onmessage = null;
  }
  triggerOpen() { if (this.onopen) this.onopen(); }
  triggerMessage(data) { if (this.onmessage) this.onmessage({ data }); }
}

global.WebSocket = MockWebSocket;

test('handles incoming WebSocket message', async () => {
  const ws = new WebSocket('ws://localhost');
  ws.triggerOpen();
  ws.triggerMessage('{"type":"ping"}');
  // 断言业务逻辑是否响应了该消息
});

处理时序与清理(避免测试污染)

fetch 和 WebSocket 都可能引发副作用(如未关闭连接、未清除监听器),导致测试间相互干扰。务必在每个测试后重置 mock 并清理资源。

  • 使用 beforeEach(() => { jest.clearAllMocks(); }) 清空调用记录和返回值
  • 若被测模块内部创建了 WebSocket 实例,测试中应模拟其 close() 行为并验证是否被调用
  • 对长时间运行的异步操作(如重连逻辑),可设置 jest.setTimeout(10000) 防止超时失败
  • 避免在测试中使用 setTimeout 等不可靠延时,优先用 waitFor 或直接触发事件

进阶:组合测试真实交互流程

当模块同时使用 fetch 初始化 + WebSocket 持续通信时,测试重点是**状态流转是否正确**。例如:先 fetch 获取 token,再用 token 建立 WebSocket 连接。

  • 按执行顺序依次 mock fetch 返回 token,再 mock WebSocket 构造并模拟认证成功消息
  • 断言最终状态(如连接标志位、缓存数据、UI 回调是否触发)
  • 用 jest.runAllTimers() 处理内部 setInterval(如心跳检测)

关键不是“像生产一样跑通”,而是“验证每一步依赖是否被正确使用、错误路径是否被覆盖”。比如模拟 fetch 失败后是否跳过 WebSocket 连接,或 WebSocket 关闭后是否自动重试。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

javascript js websocket

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

5606

5

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

2023.07.04

1369

3

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

2023.07.04

5544

6

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

2023.09.01

1020

4

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

1996

5

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

2023.09.04

3865

4

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

2023.09.12

5073

6

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

2023.09.20

3320

5

java访问控制修饰符介绍
java访问控制修饰符介绍

java访问控制修饰符有四种,分别是public、protected、private、默认访问修饰符。详细介绍:1、public,public是最宽松的访问控制修饰符,被修饰的类、方法和变量可以被任何其他类访问,当一个类、方法或变量被声明为public时,它们可以在任何地方被访问,无论是同一个包中的类还是不同包中的类;2、protected修饰符等等。

2023.09.20

1068

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebStorm 官方调试文档
WebStorm 官方调试文档

共0课时 | 0人学习

React 教程
React 教程

共58课时 | 12.4万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 6.8万人学习