You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何消除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 --detectOpenHandles to 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:22:19