如何在Jest中为异步生成器函数编写单元测试并正确Mock ReadStream
解决方案
问题根因
你当前测试失败的核心原因是 mock 的 fs.createReadStream 返回了空对象,没有实现 Symbol.asyncIterator 异步迭代器接口,无法被 for await...of 语法遍历。
具体实现方案
有两种常用的实现方式,都可以正确模拟可迭代的 ReadStream 对象:
方案1:手动实现异步迭代器(轻量无额外依赖)
直接给 mock 返回的对象挂载异步迭代器方法,返回你预设的测试块即可,不需要引入额外依赖。
方案2:用 Node 内置 Readable 生成模拟流
如果需要更贴近真实流的行为,可以用 stream.Readable.from 直接生成可迭代的流对象,适配更复杂的流行为测试场景。
完整修改后的测试代码
import fs from 'fs'; import os from 'os'; import path from 'path'; import { WorkDirUtils } from './你的模块路径'; // jest.mock 要放在模块作用域顶部,不要放在 describe 内部 jest.mock('fs'); jest.mock('os'); describe('Work Dir Utils', () => { let workDirUtils: WorkDirUtils; // 预设的测试块数据 const mockChunks = [Buffer.from('first chunk'), Buffer.from('second chunk'), Buffer.from('last chunk')]; beforeEach(() => { (os.tmpdir as jest.Mock).mockReturnValue('/tmp'); (fs.mkdtempSync as jest.Mock).mockReturnValue('/tmp/folder/pref-rand'); // mock createReadStream返回带异步迭代器的对象,用方案1的实现 (fs.createReadStream as jest.Mock).mockReturnValue({ [Symbol.asyncIterator]: async function* () { for (const chunk of mockChunks) yield chunk; } }); // 方案2的实现替换上面的mock返回值即可: // (fs.createReadStream as jest.Mock).mockReturnValue(require('stream').Readable.from(mockChunks)); workDirUtils = new WorkDirUtils(); workDirUtils.createTempDir('pref-'); }); afterEach(() => { jest.clearAllMocks(); }); it('should read chunks of a file using generator', async () => { const testFile = path.join(__dirname, './fixtures/manifest.ts'); const testChunkSize = 1024 * 1024 * 1024; const receivedChunks: Buffer[] = []; for await (const chunk of workDirUtils.readChunks(testFile, testChunkSize)) { expect(chunk).toBeInstanceOf(Buffer); receivedChunks.push(chunk); } // 校验返回的块和预设的一致 expect(receivedChunks).toEqual(mockChunks); // 校验createReadStream参数传递正确 expect(fs.createReadStream).toHaveBeenCalledWith( path.join('/tmp/folder/pref-rand', testFile), { highWaterMark: testChunkSize } ); }); });
额外优化建议
- 可以单独新增测试用例覆盖异常分支,验证 cwd 未设置时是否正确抛出错误
- 如果需要测试流报错场景,可以在模拟的异步迭代器中主动抛出错误,验证上层逻辑的容错处理
内容的提问来源于stack exchange,提问作者Balint Laszlo
相关产品推荐
相关产品推荐

