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

Jest测试Promise.all拒绝场景时遇undefined问题的解决方法

问题分析与解决方案

你的问题核心出在mock方式不正确或者目标函数内部吞掉了Promise的拒绝状态,导致funcToTest没有按预期抛出拒绝。以下是具体解决步骤:

1. 确认funcToTest的逻辑正确性

首先检查funcToTest是否在内部捕获了Promise.all的错误却没有重新抛出——这会导致函数从拒绝状态变为resolved状态,返回undefined(也就是你看到的received为undefined的原因)。

错误的函数写法(吞掉错误)

async function funcToTest() {
  try {
    const [list1, list2, list3] = await Promise.all([
      module1.getList1(),
      module2.getList2(),
      module3.getList3()
    ]);
    return { list1, list2, list3 };
  } catch (err) {
    // 仅打印错误但不重新抛出,导致函数返回resolved的undefined
    console.error(err);
  }
}

正确的函数写法(传递拒绝状态)

如果需要处理404异常,仅保留该逻辑,其他错误重新抛出:

async function funcToTest() {
  try {
    const [list1, list2, list3] = await Promise.all([
      module1.getList1(),
      module2.getList2(),
      module3.getList3()
    ]);
    return { list1, list2, list3 };
  } catch (err) {
    // 仅忽略404错误,其他错误重新抛出
    if (err.status !== 404) {
      throw err;
    }
    return { list1: [], list2, list3 };
  }
}

如果不需要额外处理,直接去掉try/catch,让Promise.all的拒绝状态自然传递:

async function funcToTest() {
  const [list1, list2, list3] = await Promise.all([
    module1.getList1(),
    module2.getList2(),
    module3.getList3()
  ]);
  return { list1, list2, list3 };
}

2. 正确Mock module1.getList1

必须确保mock的函数返回rejected状态的Promise,而不是同步抛出异常或返回resolved Promise。Jest提供了两种可靠方式:

方式1:使用mockRejectedValue(推荐)

// 全局mock module1
jest.mock('./module1', () => ({
  getList1: jest.fn().mockRejectedValue(new Error('非404异常'))
}));

方式2:用async函数模拟抛异常

因为async函数内部抛出异常时,会自动返回rejected状态的Promise:

jest.mock('./module1', () => ({
  getList1: jest.fn().mockImplementation(async () => {
    throw new Error('非404异常');
  })
}));

3. 正确断言拒绝状态

使用Jest的rejects匹配器,或try/catch手动捕获错误进行断言:

方式1:用expect().rejects.toThrow()

test('当getList1抛出非404异常时,funcToTest应该拒绝', async () => {
  // 可以在测试内动态修改mock的错误信息
  const testError = new Error('测试用非404异常');
  require('./module1').getList1.mockRejectedValue(testError);

  // 断言函数拒绝并匹配错误
  await expect(funcToTest()).rejects.toThrow(testError);
  // 或匹配错误文本
  await expect(funcToTest()).rejects.toThrow('测试用非404异常');
});

方式2:try/catch捕获断言

test('当getList1失败时,funcToTest拒绝', async () => {
  const testError = new Error('测试用非404异常');
  require('./module1').getList1.mockRejectedValue(testError);

  let caughtError;
  try {
    await funcToTest();
  } catch (err) {
    caughtError = err;
  }

  // 断言错误被捕获,且符合预期
  expect(caughtError).toBeDefined();
  expect(caughtError.message).toBe('测试用非404异常');
});

4. 排查Promise.allSettled显示全fulfilled的问题

如果用Promise.allSettled测试时所有Promise都显示fulfilled,说明你的getList1 mock实际上返回了resolved状态的Promise。检查mock代码:

  • 避免使用mockResolvedValue或错误地返回普通值
  • 确保mock的是异步函数的拒绝状态,而非同步抛出异常(同步异常会被Promise包装为rejected,但如果mock写法错误可能导致意外)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 13:01:03