测试异步解析逻辑需用 stream.readable 模拟文件流,覆盖正常分块、中断、错误等场景;mock fs.createreadstream;断言事件监听、错误清理及空流处理;辅以真实小文件 smoke test。

测试包含文件流读取的异步解析逻辑,核心是**绕过真实文件 I/O,用可控制的模拟流替代 fs.createReadStream,并确保解析逻辑能正确处理流式数据、错误、暂停/恢复等边界情况**。真实读文件不仅慢、依赖环境,还难以触发如“流中断”“部分数据”“高延迟”等关键场景。
用 Readable 模拟各种文件流行为
Node.js 的 stream.Readable 可以按需推送数据,精准控制流的节奏和状态:
- 正常完整流:调用
push(chunk)多次后push(null)结束 - 大文件分块:用
setImmediate或setTimeout延迟后续push,模拟网络/磁盘延迟 - 流提前关闭:创建流后立即调用
destroy(),验证解析器是否妥善清理资源 - 错误注入:在
push前调用emit('error', new Error('EACCES'))
示例(模拟 CSV 流解析):
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
const { Readable } = require('stream');
const mockStream = new Readable({ read() {} });
mockStream.push('name,age\n');
mockStream.push('Alice,30\n');
mockStream.push('Bob,25\n');
mockStream.push(null); // EOF
// 传给你的 parseCSV(stream) 函数即可
用 sinon 或 jest.mock 替换 fs.createReadStream
避免测试中真正访问文件系统。推荐方式:
-
Jest 用户:在测试前
jest.mock('fs'),然后在 mock 实现中返回你构造的Readable -
sinon 用户:用
sinon.stub(fs, 'createReadStream').returns(mockStream) - 注意:如果解析逻辑内部还用了
fs.promises.readFile等,也要一并 mock
断言要覆盖流生命周期的关键点
别只检查最终输出。流式解析容易在以下环节出错,测试必须显式验证:
- 解析结果是否与输入数据一致(内容正确性)
- 是否监听了
'data'、'end'、'error'、'close'事件 - 遇到错误时是否自动销毁输入流(防止内存泄漏)
- 调用
stream.destroy()后,解析器是否停止处理、不抛未捕获异常 - 对空流(
push(null)立即结束)是否安全处理
集成真实小文件做 smoke test(非必需但推荐)
单元测试用模拟流覆盖逻辑,再加一个轻量级集成测试:放一个 2–3 行的真实 CSV/JSONL 文件在 __tests__/fixtures/ 下,用 fs.createReadStream 读它并断言结果。这能捕捉因 Node 版本、编码(如 BOM)、行尾符等导致的意外问题,执行快、不破坏可靠性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










