Jest测试(Body as any).pipe(zlib.createGunzip())时出现TypeError排查
问题原因
你的错误根源主要有两点:
- AWS SDK v3的S3返回Body是SdkStream类型,并非Node原生Readable流,你直接用
as any强制转换后调用pipe,实际环境中可能因SDK隐式兼容正常运行,但测试环境里用sdkStreamMixin包装的流未正确实现pipe的兼容逻辑,导致调用失败。 - 测试代码中文件路径不匹配:你打印的Body路径是
./tests/data/GLOBAL.csv,但测试里创建的是./tests/data/test.csv,流可能因文件路径错误初始化异常,间接引发pipe调用时的内部错误。
错误栈指向Readable.pipe里的dest.on('unpipe'),本质是调用pipe时,Body并非合法的Node可读流,导致内部逻辑报错。
解决方案
方案1:修正业务代码(推荐,符合SDK规范)
AWS SDK v3的SdkStream需要转换为Node原生流才能使用pipe,引入@aws-sdk/util-stream-node工具包做转换:
// 导入转换工具及类型 import { toNodeReadableStream } from "@aws-sdk/util-stream-node"; import type { SdkStream } from "@aws-sdk/types"; // ... const { Body } = await s3.send(command); // 先转换为Node可读流,再调用pipe const nodeStream = toNodeReadableStream(Body as SdkStream); const input = nodeStream.pipe(zlib.createGunzip());
方案2:修正测试代码(不修改业务代码时使用)
测试中直接返回Node原生ReadStream,无需用sdkStreamMixin包装(适配你业务代码里as any的处理逻辑):
it('Import file', async () => { // 修正路径为实际打印的GLOBAL.csv const stream = createReadStream('./tests/data/GLOBAL.csv'); // 直接返回原生流,跳过sdkStreamMixin包装 s3Mock.on(GetObjectCommand).resolves({ Body: stream }); const event: any = {}; // 补充event必要属性,避免undefined问题 let context: any = {}; const result = await handler(event, context); console.log(result); });
额外检查项
- 确认
zlib模块已正确导入(const zlib = require('zlib')或import zlib from 'zlib'),保证zlib.createGunzip()能返回有效转换流。 - 测试文件路径必须与实际读取的文件一致,避免流因文件不存在初始化异常。
内容的提问来源于stack exchange,提问作者Fernando de Santiago
相关产品推荐
相关产品推荐

