You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何fs.createWriteStream抛出的错误在Jest中无法被捕获?

为什么fs.createWriteStream的错误无法在Jest中被try/catch或Promise.catch捕获?

这个问题我之前也碰到过,核心原因是fs.createWriteStream是基于事件驱动的API,并非Promise友好的,你当前的错误没有被纳入Promise链的处理流程,所以try/catch、.then/.catch甚至Jest的rejects.toThrow都没法正确捕获它。

问题根源拆解

当你调用fun(t)时,它内部大概率使用了fs.createWriteStream来写入文件,但这个流的错误是通过error事件触发的,而不是通过Promise的reject状态抛出。也就是说:

  • 你的fun(t)返回的Promise并没有绑定流的error事件,所以即使流抛出错误,Promise也不会进入reject状态
  • 这种情况下,错误会“逃逸”出Promise链,变成Jest能检测到的未捕获异常,这就是你看到直接输出ENOENT错误的原因

对比你之前的rawFileDownloaderFactory测试能正常工作,是因为它依赖的fetch是原生Promise API,或者内部已经把所有回调式的错误都转化成了Promise的reject,所以错误能被Jest的rejects.toThrow正确捕获。

解决方案

1. 先修复datafileWriterFactory的内部实现

你需要把fs.createWriteStream的操作Promise化,手动绑定流的error和finish事件来控制Promise的状态:

// 示例:在datafileWriterFactory内部封装stream操作
const fs = require('fs');

function writeToFile(path, content) {
  return new Promise((resolve, reject) => {
    const writeStream = fs.createWriteStream(path);
    
    writeStream.write(content);
    writeStream.end();

    // 流写入完成时resolve Promise
    writeStream.on('finish', () => resolve());
    // 关键:把流的error事件转化为Promise的reject
    writeStream.on('error', (err) => reject(err));
  });
}

这样,当流触发error事件时,Promise会进入reject状态,fun(t)返回的Promise就会带上这个错误,后续的错误处理逻辑就能生效了。

2. 修正测试代码的写法

确保你用Jest的正确语法测试Promise的reject,不需要额外的try/catch或.then/.catch(除非你需要调试):

test('throws when it cannot write to the file', async () => {
  const fun = datafileWriterFactory(fetch)(selector, parser)(noop);
  
  // 直接测试Promise的reject,Jest会自动等待并验证
  await expect(fun(t)).rejects.toThrow();
  
  // 如果需要更精确的验证,可以指定错误类型或消息
  // await expect(fun(t)).rejects.toThrow('ENOENT');
  // await expect(fun(t)).rejects.toThrow('no such file or directory');
});

补充:为什么原有测试代码没捕获到错误?

你的原有测试代码中:

  • .then(() => console.log("WORKED")) 不会触发,因为流没完成写入就报错了
  • .catch((e) => console.error("FAILED", e)) 不会触发,因为Promise没有进入reject状态
  • 外层的try/catch也抓不到,因为await的Promise没有抛出reject,流的错误是独立的未捕获事件

Jest会自动检测到这类未捕获的异常,所以直接输出了错误信息。

内容的提问来源于stack exchange,提问作者GTF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:07:55