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

Node 12升级Node 16后Promise测试用例失败问题

问题根因
  • 首先是Node.js版本的默认行为变更:从Node v15开始,所有未挂载catch处理的Promise拒绝默认会直接抛出ERR_UNHANDLED_REJECTION错误终止进程,而v12及更早版本仅会打印警告不会中断执行,这是版本升级后报错直接暴露的核心背景。
  • 你的Mock代码存在悬空的Promise拒绝:Mock响应里的json方法内部创建了Promise.reject(new Error()),但没有return这个Promise,导致这个被拒绝的Promise完全脱离了后续的Promise调用链,业务代码里挂载的.catch()根本捕获不到它,成了无主的拒绝,刚好触发Node16的报错规则。
  • 测试的等待逻辑完全错误:你写的await thePromise.then().catch()只等待了最外层mock的fetch Promise resolve,没有等待后续response.json()、链式then/catch执行、React状态更新、组件重渲染这些微任务跑完,断言触发时错误状态还没更新到DOM上,自然拿到null快照。之前加的空catch没有任何实际错误处理逻辑,只是碰巧多延迟了一个微任务,完全没解决悬空Promise的核心问题。
修复方案
  1. 先修复Mock逻辑,让rejected Promise正确进入调用链
    把json方法的写法改成直接返回Promise,不要在大括号里创建了Promise又不return,否则这个reject永远不会被业务代码的catch捕获:
// 错误写法:无return,Promise.reject脱离调用链
const thePromise = Promise.resolve({
  json: () => {
    Promise.reject(new Error());
  },
});

// 正确写法:返回rejected Promise,让它进入后续链式调用
const thePromise = Promise.resolve({
  json: () => Promise.reject(new Error()),
});
  1. 替换错误的等待逻辑,等所有异步操作完成再断言
    不要手动await你自己mock的外层Promise,等微任务队列排空、组件完成重渲染后再做快照断言:
it('should test', async () => {
  const thePromise = Promise.resolve({
    json: () => Promise.reject(new Error()),
  });

  validateCode.mockReturnValueOnce(thePromise);

  const rendered = renderModule({ state: { code: 'mockRefCode' } });
  rendered.find('#btn').simulate('click');

  // 等待所有Promise链、状态更新的微任务执行完成
  await Promise.resolve();
  // Enzyme环境需要手动刷新wrapper获取最新DOM
  rendered.update();

  expect(rendered.find('#error')).toMatchSnapshot();
});

如果是用React Testing Library写的测试,直接用waitFor包裹断言即可,不需要手动写等待逻辑,稳定性更高。

修复后,mock的reject会被业务代码的catch正常捕获,触发setValidationError渲染错误提示,也不会存在未处理的Promise拒绝,Node16环境下可以正常跑通测试、匹配正确快照。

内容的提问来源于stack exchange,提问作者karvai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:57:06