news 2026/9/11 5:40:33

ASP.NET Core SignalR TypeScript 客户端单元测试完全指南:Jest 运行、过滤与调试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ASP.NET Core SignalR TypeScript 客户端单元测试完全指南:Jest 运行、过滤与调试

ASP.NET Core SignalR TypeScript 客户端单元测试完全指南:Jest 运行、过滤与调试

【免费下载链接】aspnetcoreASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.项目地址: https://gitcode.com/GitHub_Trending/as/aspnetcore

ASP.NET Core SignalR 的 JavaScript/TypeScript 客户端(@microsoft/signalr@microsoft/signalr-protocol-msgpack)使用 Jest 官方文档,系统讲解如何在clients/ts目录下构建库、运行全部/部分/单个测试,以及在 Visual Studio Code 中调试测试用例。读完本文,你将掌握 SignalR TypeScript 客户端单元测试的完整命令集、Jest 的文件名与-t过滤技巧,以及基于 VS Code 的断点调试工作流。

一、测试框架与前置条件

SignalR 的 TypeScript 客户端单元测试建立在以下技术栈之上:

  • Jest:测试运行器与断言框架(当前仓库 package.json 中锁定jest^29.5.0);
  • ts-jest:Jest 的 TypeScript 预处理器,自动完成类型检查与转译,省去单独的编译步骤;
  • jest-jasmine2:以 Jasmine 2 风格运行测试的 runner(见 jest.config.js 中testRunner: "jest-jasmine2"),因此测试代码使用describe/it的 Jasmine 风格组织;
  • @types/jest / @types/node:为测试代码提供类型定义。

在开始之前需要满足两个前置条件:

  1. 已安装Node.js
  2. 自上次clean之后,至少运行过一次./build.cmd /t:Restore,确保仓库的构建基础设施(包括 npm 依赖还原)就绪。

注意:文档中给出的构建命令./build.cmd /t:Restore是 Windows 环境写法;Linux/macOS 下对应脚本为仓库根目录的 restore.sh(或./build.sh,视仓库构建脚本而定),请根据实际运行环境选用。

所有命令都必须从clients/ts目录(即 src/SignalR/clients/ts)下执行,因为 npm 脚本与 Jest 配置均以该目录为工作根目录。

测试的组织方式

从仓库源码看,单元测试按包划分为两个测试目录:

  • signalr/tests:核心客户端@microsoft/signalr的测试,覆盖AbortSignalHttpConnectionHubConnectionHubConnectionBuilderJsonHubProtocolLongPollingTransportWebSocketTransportServerSentEventsTransportTextMessageFormatUserAgent等主题;
  • signalr-protocol-msgpack/tests:MessagePack 协议扩展包@microsoft/signalr-protocol-msgpack的测试,包含BinaryMessageFormatter.test.tsMessagePackHubProtocol.test.ts

测试文件统一采用*.test.ts命名,例如 AbortSignal.test.ts、JsonHubProtocol.test.ts。Jest 的匹配规则定义在 jest.config.js 的testRegex(/__tests__/.*|(\.|/)(test|spec))\.(jsx?|tsx?)$,即命中.test.ts/.spec.ts等模式的文件才会被当作测试执行。

二、运行测试前先构建库

SignalR 的单元测试会直接引用打包产物。在 jest.config.js 中可以看到一个关键映射:

moduleNameMapper: { "^@microsoft/signalr$": "<rootDir>/signalr/dist/cjs/index.js" }

也就是说,测试代码中import { ... } from "@microsoft/signalr"实际解析到signalr/dist/cjs/index.js——这是npm run build生成的 CommonJS 打包产物。因此,每次修改库源码后,都必须先重新构建,再运行测试,否则测试运行的仍是旧的构建结果。

clients/ts目录下执行:

> npm run build

该命令会构建@microsoft/signalr@microsoft/signalr-protocol-msgpack两个库(底层通过 webpack/tsc 完成,相关配置见 webpack.config.base.js 与 tsconfig.base.json)。同时,npm run build也会在signalr/dist/cjs下产出 Jest 所需的 CommonJS 入口。

三、运行全部测试

clients/ts目录下执行:

> npm test

该命令实际调用的是jest --config ./jest.config.js(见 package.json 中的test脚本)。在进入 Jest 之前,pretest钩子还会先运行 ESLint 对两个测试目录做静态检查:

"pretest": "npm run lint-signalr & npm run lint-signalr-msgpack"

npm test会运行两个包的全部*.test.ts文件,并在终端输出每个套件/用例的通过情况。此外 package.json 还提供了覆盖率脚本npm run coverage(等价于jest --config ./jest.config.js --coverage),需要度量代码覆盖率时可使用它。

测试结果默认输出到终端;同时 jest.config.js 配置了jest-junitreporter,会把 JUnit 格式的结果写入../../../../artifacts/log/<platform>.signalr.junit.xml(即仓库根目录的 artifacts/log 下),便于 CI 集成。

四、运行特定文件中的全部测试

npm test接受附加参数并透传给 Jest:

> npm test -- FileName

其中FileName可以是路径的一个子串,Jest 会运行路径中包含该子串的所有测试文件。文档强调:即使在 Windows 上,路径分隔符也请使用/,因为参数最终由 Node 解析。

官方文档给出的示例(均基于clients/ts目录):

命令运行范围
npm test -- signalr/testsclients\ts\signalr\tests下的全部测试
npm test -- signalr-protocol-msgpack/testsclients\ts\signalr-protocol-msgpack\tests下的全部测试
npm test -- signalr/tests/clients\ts\signalr\tests下的全部测试(尾部斜杠写法同样有效)
npm test -- signalr/tests/JsonHubProtocolsignalr/tests/JsonHubProtocol.test.ts
npm test -- JsonHubProtocol同样运行signalr/tests/JsonHubProtocol.test.ts(因为它是唯一匹配该子串的测试文件)

由此可见,文件过滤是“子串包含”匹配而非“前缀/后缀”匹配,JsonHubProtocolsignalr/tests/JsonHubProtocol都能命中同一文件。实际仓库中该文件为 JsonHubProtocol.test.ts,其中包含对 Invocation 消息读写、Date 参数序列化、headers 传递、消息轮询等场景的断言。

五、运行单个测试

运行单个测试有两种方式,各有适用场景。

方式一:.only临时标记(最简单)

Jest 支持在it上追加.only,被标记的用例会成为该文件中唯一运行的测试。官方文档的示例:

describe("A suite of tests", () => { describe("A sub-suite of tests", () => { it.only("will run", () => { }); it("will not run", () => { }); }); describe("Another sub-suite of tests", () => { it("will not run either", () => { }); }); });

注意两点:

  • 若同时运行多个文件(例如不带参数直接npm test),其他文件中的测试仍然会照常运行.only只对所在文件生效;
  • 调试完务必移除.only,避免后续提交时误伤其他用例。

方式二:-t参数按名称过滤(无需改代码)

Jest 的-t参数接收一个子串模式,用于匹配测试的完整名称(由describe名称 +it名称拼接而成)。为了加快执行速度,官方建议把-t与文件路径过滤参数配合使用。

以官方文档中的示例代码(该示例与仓库真实文件 AbortSignal.test.ts 结构一致)为例:

describe("AbortSignal", () => { describe("aborted", () => { it("is false on initialization", () => { // ... }); it("is true when aborted", () => { // ... }); }); describe("onabort", () => { it("is called when abort is called", () => { // ... }); }); });

对应命令与运行结果:

命令运行的测试
npm test -- AbortSignal -t "AbortSignal aborted"AbortSignal aborted is false on initializationAbortSignal aborted is true when aborted
npm test -- AbortSignal -t "is called when abort is called"AbortSignal onabort is called when abort is called

第一条命令中,AbortSignal把文件过滤到 AbortSignal.test.ts,-t "AbortSignal aborted"匹配名称中同时包含这两个词的用例(外层describe("AbortSignal")+ 内层describe("aborted")组合成前缀AbortSignal aborted)。第二条命令的-t子串只命中onabort子套件中的it("is called when abort is called"),因为其完整名称为AbortSignal onabort is called when abort is called

对比两种方式:.only需要修改测试源码、适合快速聚焦单个用例;-t不动源码、适合按名称模式批量筛选,二者可以组合使用(例如在文件中标记.only,再用 VS Code 的“Jest - Current File”调试)。

六、在 Visual Studio Code 中调试测试

仓库文档提供了两种开箱即用的 VS Code 调试配置,无需手动编写launch.json

调试全部测试

  1. 打开 VS Code 左侧的Run and Debug(调试)面板;
  2. 在顶部的配置下拉框中选择"Jest - All"
  3. 点击播放按钮,或直接按F5

该配置会在调试器下运行全部单元测试,适合全局回归排查。

调试当前文件中的全部测试

  1. 打开 VS Code 左侧的Run and Debug(调试)面板;
  2. 在顶部的配置下拉框中选择"Jest - Current File"
  3. 点击播放按钮,或直接按F5

该配置只运行当前打开的编辑器文件中的测试,配合.only即可精确调试单个用例。官方文档特别提醒:将 "Jest - Current File" 与.only搭配使用,是调试单个测试的最便捷方式

提示:仓库内未在clients/ts下发现.vscode/launch.json,上述两个配置由仓库的 VS Code 任务/调试基础设施提供(该文档即为其权威说明)。若你的环境中未出现这两个配置项,可确认已通过仓库构建脚本完成 VS Code 工作区设置,或参照 Jest 官方文档配置等价调试参数。

七、调试定位的源码参考

当某个测试失败时,可以借助以下仓库路径快速定位被测实现与相关测试,形成“源码—测试”对照:

  • 核心客户端源码目录:src/SignalR/clients/ts/signalr/src(包含HubConnectionHttpConnectionJsonHubProtocol、各传输实现等);
  • 核心客户端测试目录:src/SignalR/clients/ts/signalr/tests;
  • MessagePack 协议包源码:src/SignalR/clients/ts/signalr-protocol-msgpack/src,对应测试在 src/SignalR/clients/ts/signalr-protocol-msgpack/tests;
  • 与单元测试配套的还有浏览器端功能测试文档 JSFunctionalTests.md,用于端到端验证传输与协议在真实浏览器中的行为。

八、常见问题与最佳实践

  1. 改了源码但测试结果没变:多半是忘记先执行npm run build。由于moduleNameMapper指向signalr/dist/cjs/index.js,不重新构建就无法验证最新代码。
  2. 过滤条件不生效:确认FileName是路径子串且使用/分隔符;-t的子串需与describe+it拼接后的完整名称匹配。
  3. 提交前清理.only.only是临时调试标记,遗留到 CI 会导致大量用例被跳过。
  4. 充分利用类型检查:tsconfig.jest.json 继承 tsconfig.base.json,开启strictnoImplicitAny等严格选项,测试代码同样享受完整类型检查,遇到编译错误时先修类型再跑测试。

九、命令速查表

目的命令(在clients/ts目录下)
构建库(改源码后必跑)npm run build
运行全部测试npm test
运行某路径下的全部测试npm test -- signalr/tests
运行单个测试文件npm test -- JsonHubProtocol
按名称子串运行指定文件内的用例npm test -- AbortSignal -t "AbortSignal aborted"
生成覆盖率报告npm run coverage
调试全部测试(VS Code)选择 "Jest - All" 后按 F5
调试当前文件测试(VS Code)选择 "Jest - Current File" 后按 F5,建议配合.only

按照上述流程,你可以从“改代码 →npm run buildnpm test -- <过滤>→ 断点调试”的完整闭环中高效迭代 SignalR TypeScript 客户端的开发与验证工作。

【免费下载链接】aspnetcoreASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.项目地址: https://gitcode.com/GitHub_Trending/as/aspnetcore

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 5:38:39

上位机开发求职指南:从技术栈到行业定位的全流程拆解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 5:37:29

CMSIS-5架构深度解析:嵌入式底层契约与分层治理实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 5:36:44

ESP32-P4 USB Host驱动U盘实战:从枚举失败到FatFS挂载

1. 项目概述&#xff1a;为什么在ESP32-P4上跑U盘不是“插上就能用”的简单事你手头刚拿到一块标着“DNESP32P4”的开发板&#xff0c;拆开文档翻到第四十七章——《USB U盘实验》&#xff0c;心里可能已经浮现出画面&#xff1a;接根USB线&#xff0c;插个U盘&#xff0c;串口…

作者头像 李华
网站建设 2026/9/11 5:36:40

机器学习大作业实战:多项式拟合、GMM与逻辑回归全解析

简介&#xff1a;面向机器学习课程设计与期末大作业的完整资料包&#xff0c;涵盖多项式拟合正弦函数、GMM聚类与逻辑回归三大经典实验&#xff0c;并附期末考试题。适合计算机、人工智能等专业学生用于课设、大作业或项目演示&#xff0c;也适合初学者参照源码进阶学习。包内主…

作者头像 李华
网站建设 2026/9/11 5:35:52

Oracle EBS总账模块MassAllocation功能详解与实战

1. Oracle EBS总账模块中的MassAllocation功能解析MassAllocation&#xff08;大量分摊&#xff09;是Oracle E-Business Suite&#xff08;EBS&#xff09;总账模块&#xff08;General Ledger, GL&#xff09;中一个强大的分摊工具。作为从业15年的Oracle财务系统顾问&#x…

作者头像 李华
网站建设 2026/9/11 5:35:40

私有化部署的RPA+AI落地实践:从发票识别到数据不出域

今年上半年&#xff0c;我接到一个老客户的电话&#xff0c;上来就问我&#xff1a;之前建议的云上AI接口&#xff0c;能不能直接把财务发票识别接进来&#xff1f;我说能&#xff0c;但客户财务部的主任在旁边补了一句&#xff1a;这些发票数据不能出公司网络。于是话题从“哪…

作者头像 李华