Node 测试抛错却通过
Node none 隔离测试文件先注册再加载抛错,可能少跑测试却退出 0。核对 26.11.1 仍存的分支与默认 process 隔离、测试数量验收。
测试文件加载到一半抛出异常,后面的测试没有注册,运行结果却是成功、退出码为 0。先检查是否使用了 Node 的 --test-isolation=none,以及异常之前是否已经调用过 test()。
Node 26.10.0 有对应的实际表现。已核对的正式版 26.11.1 中,相关无进程隔离分支仍保留这一缺口,不能把升级到这个版本写成修复。
异常发生在注册之后
下面的文件只用于说明加载顺序,最后一个测试不会被执行到:
import { test } from 'node:test';
test('registered first', () => {});
null.x;
test('never registered', () => {});
null.x 不在测试回调里面。它发生在模块加载阶段,而且前面已经注册了一个顶层测试。
在已核对的 none 路径里,runner 捕获文件导入错误后,只有当该文件没有新增顶层子测试时,才创建一个失败占位测试。前面的注册已经改变了子测试数量,导入错误就可能没有被转成文件级失败。已有测试可以通过,后半段却静默丢失。
因此,“通过一个测试”和“完整加载了这个测试文件”是不同事实。若异常在第一个 test() 之前发生,条件也不同,不能用那种表现证明这个窗口不存在。
先恢复需要的文件隔离
--test-isolation=none 会让测试文件在同一个进程中执行。Node 默认使用 process 隔离,让各测试文件在子进程里运行。项目不依赖共享进程行为时,可以移除显式的 none,恢复默认路径。
在使用本文已核对选项形态的版本中,也可以明确指定:
node --test --test-isolation=process path/to/existing.test.mjs
路径应替换为项目已有的测试文件;这条命令会执行其测试代码,应只用于受控测试环境。启动脚本、环境变量或 CI 参数如果仍注入 none,也要一并核对最终选项,不能只改一处文件名。
恢复进程隔离会改变全局状态、单例和其他进程内共享方式。确实需要 none 的测试体系,应先审查这种依赖,并对文件加载完整性设置单独的检查;不能为了让这一个错误被看见,未经评估就迁移整套执行架构。
检查计划数量与加载错误
除了失败数和退出码,还要核对预期的测试文件、测试数量,以及加载阶段异常是否被明确报告。少跑了测试却显示全绿,可能影响覆盖率、变异测试或其他根据执行结果做判断的工具。
对受控的错误样本,恢复隔离后应看到文件加载失败并得到失败结果;正常样本仍应完整注册和执行原有测试。如果数量变化来自测试筛选、跳过或业务条件,则按实际配置另查。
这与等待一个永不完成的 Promise 时进程退出不同:本篇是加载异常已被捕获,却没有在特定注册条件下计为失败。添加一个长时间计时器或强制保活,无法补上缺失的文件失败结果。


