使用supertest测试multer时如何创建mock文件替代磁盘真实文件
问题原因
你遇到的TypeError: source.on is not a function报错,核心是supertest的.attach()方法接收的非本地路径参数必须是Buffer或者可读流类型,你构造的普通对象不符合接口要求,supertest内部尝试把参数作为流调用事件监听方法时就会抛出异常。另外你手动构造FormData实例的方式不需要使用,supertest会自动处理multipart/form-data格式的请求体。
解决方案
方法1:Buffer构造虚拟文件(推荐,大部分测试场景适用)
直接用Node内置的Buffer生成任意大小的虚拟文件内容,无需读写本地磁盘:
const request = require('supertest'); const app = require('../app'); // 替换为你自己的express实例路径 test('校验multer文件上传数量、大小限制', async () => { // 生成10MB大小的虚拟文件内容,第二个参数可自定义填充内容 const mockFileBuffer = Buffer.alloc(10 * 1024 * 1024, 'test content'); const uploadRequest = request(app).post('/api/file-upload/'); // 循环添加12个测试文件 for (let i = 0; i < 12; i++) { uploadRequest.attach( 'files', mockFileBuffer, { filename: `test-${i}.txt`, contentType: 'text/plain' } ); } // 可根据你的multer校验规则修改预期状态码,比如超过数量限制可预期400 await uploadRequest.expect(200); });
代码说明:
Buffer.alloc可以快速生成指定大小的内存块,完全不需要操作本地磁盘.attach第三个参数可以自定义文件名、MIME类型,multer可以正常读取这些属性
方法2:流构造超大文件(适合测试大文件场景)
如果需要测试的文件体积过大,用Buffer会占用过多内存,可以用Node内置的PassThrough流构造虚拟文件,不会实际占用对等体积的内存:
const { PassThrough } = require('stream'); const request = require('supertest'); const app = require('../app'); test('校验超大文件上传限制', async () => { const mockFileStream = new PassThrough(); const targetSize = 100 * 1024 * 1024; // 模拟100MB文件 let writtenSize = 0; const chunk = Buffer.alloc(1024 * 1024, '0'); // 每次写入1MB内容 const writeTimer = setInterval(() => { if (writtenSize >= targetSize) { mockFileStream.end(); clearInterval(writeTimer); return; } mockFileStream.write(chunk); writtenSize += chunk.length; }, 0); await request(app) .post('/api/file-upload/') .attach('files', mockFileStream, { filename: 'large-test.txt', contentType: 'text/plain' }) .expect(413); // 示例:超过大小限制预期返回413状态码 });
内容的提问来源于stack exchange,提问作者JSEvgeny
相关产品推荐
相关产品推荐

