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

Jest测试中循环内使用expect未抛预期错误的解决办法求助

循环遍历枚举时Jest测试中的expect语句无法触发预期错误

我正在重构单元测试,发现遍历枚举的循环内的expect语句无法正常工作。原本逐个枚举值编写的测试可以正常触发预期错误,但改用Object.keys(Status).map循环重构后,无法触发错误。

原测试代码:

it('should block approval of ads if status is not in pending revision', async () => {
  mockAdsRepository.findOne = jest.fn(() =>
    Promise.resolve({ ...adsDto, status: Status.REJECTED }),
  );
  await expect(service.approve(1, 1)).rejects.toThrow(BadRequestException);

  mockAdsRepository.findOne = jest.fn(() =>
    Promise.resolve({ ...adsDto, status: Status.UNPUBLISH }),
  );
  await expect(service.approve(1, 1)).rejects.toThrow(BadRequestException);

  // error trigger, working
  // mockAdsRepository.findOne = jest.fn(() =>
  //   Promise.resolve({ ...adsDto, status: Status.PENDING_REVISION }),
  // );
  // await expect(service.approve(1, 1)).rejects.toThrow(BadRequestException);

  //refactor
  Object.keys(Status).map(async (key) => {
    if (Status[key] !== Status./*changing this value for error triggers not working*/ ) {
      mockAdsRepository.findOne = jest.fn(() =>
        Promise.resolve({ ...adsDto, status: Status[key] }),
      );

      await expect(service.approve(1, 1)).rejects.toThrow(
        BadRequestException,
      );
    }
  });
});

问题原因

  1. 未等待异步操作完成:map返回的是异步Promise数组,但未用await等待所有Promise执行完毕,Jest会直接结束测试,不会等待循环内的expect执行。
  2. 枚举遍历方式错误:Object.keys(Status)会遍历枚举的键(如果是TypeScript枚举,还会包含反向映射的字符串键),可能导致遍历到非预期的枚举值。
  3. mock覆盖风险:循环内频繁赋值mockAdsRepository.findOne,可能导致后续测试的mock被提前覆盖。

解决方案

1. 等待所有异步测试完成

用Promise.all包裹循环生成的Promise数组,并await它,确保Jest等待所有测试执行完毕。

2. 正确遍历枚举值

使用Object.values(Status)直接获取枚举值,过滤掉不需要测试的状态,避免遍历到枚举的键。

3. 优化mock管理

每次测试前可以清除mock,避免残留影响,或直接在循环内赋值独立的mock实现。

修改后的代码:

it('should block approval of ads if status is not in pending revision', async () => {
  const excludedStatus = Status.PENDING_REVISION;
  // 获取所有需要测试的枚举值,排除允许通过的状态
  const targetStatuses = Object.values(Status).filter(
    status => status !== excludedStatus && typeof status === 'string' // 根据枚举类型调整类型判断
  );

  // 等待所有异步测试完成
  await Promise.all(targetStatuses.map(async (status) => {
    // 赋值新的mock实现
    mockAdsRepository.findOne = jest.fn(() =>
      Promise.resolve({ ...adsDto, status }),
    );

    await expect(service.approve(1, 1)).rejects.toThrow(BadRequestException);
  }));
});

补充说明

  • 如果是数字类型的TypeScript枚举,Object.values会同时返回数字值和反向映射的字符串键,需要用typeof status === 'number'(或对应类型)过滤掉无关值。
  • 若需要更独立的测试环境,可以在循环内使用jest.clearAllMocks()清除之前的mock调用记录,避免测试间的干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:59:54