如何消除Jest+MSW v2中FormData请求单元测试的泄漏警告?
问题:MSW v2迁移后FormData请求触发Jest进程退出警告
在Node18环境的React项目中,将Jest+MSW v1的单元测试迁移到MSW v2后,当请求体为FormData类型时,控制台出现以下警告:
A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with
--detectOpenHandlesto find leaks. Active timers can also cause this, ensure that.unref()was called on them.
仅在请求体为FormData(无论内容是文件还是字符串)时触发该警告,字符串或对象类型的请求体无此问题。相关测试代码如下:
测试代码1(文件作为FormData)
it('requests endpoint with a file as formdata', async () => { server.use( http.post('/endpoint', async ({ request }) => { requests.push(request); return HttpResponse.json({ data: 'some data' }); }), ); const file = new File( [fs.readFileSync(path.join(__dirname, '__fixtures__', 'file.png'))], 'file.png', ); const body = new FormData(); body.append('file', file); // internal functionality await expect(postToBackend({ endpoint: '/endpoint', body, })).resolves.toEqual({ data: 'some data' }); body.delete('file'); expect(requests).toHaveLength(1); });
测试代码2(字符串作为FormData)
it('requests endpoint with a string as formdata', async () => { server.use( http.post('/endpoint', async ({ request }) => { requests.push(request); return HttpResponse.json({ data: 'some data' }); }), ); const body = new FormData(); body.append('file', 'some form data'); // internal functionality await expect(postToBackend({ endpoint: '/endpoint', body, })).resolves.toEqual({ data: 'some data' }); body.delete('file'); expect(requests).toHaveLength(1); });
解决方案
以下几种方法可消除该警告:
1. 在Mock Handler中消费FormData请求体
MSW v2中Request对象的body是可读流,若未被消费会导致资源泄漏。在mock接口中主动读取并消费FormData:
http.post('/endpoint', async ({ request }) => { // 消费FormData,释放关联资源 await request.formData(); requests.push(request); return HttpResponse.json({ data: 'some data' }); }),
2. 测试后手动销毁Request对象
在断言完成后,主动销毁保存的Request对象,释放资源:
await expect(postToBackend({ endpoint: '/endpoint', body, })).resolves.toEqual({ data: 'some data' }); // 取消请求流并清空数组,释放引用 await requests[0].body.cancel(); requests = []; body.delete('file'); expect(requests).toHaveLength(1);
3. 完善MSW服务器的清理逻辑
在每个测试用例结束后,重置MSW处理器并清空请求数组,避免残留引用:
afterEach(() => { server.resetHandlers(); requests = []; // 清空请求数组,释放Request对象的内存引用 });
4. 临时应急:配置Jest强制退出(不推荐长期使用)
在package.json的测试脚本中添加--forceExit参数,强制Jest在测试结束后退出进程:
"scripts": { "test": "jest --forceExit" }
内容的提问来源于stack exchange,提问作者axel
相关产品推荐
相关产品推荐

