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, ); } }); });
问题原因
- 未等待异步操作完成:
map返回的是异步Promise数组,但未用await等待所有Promise执行完毕,Jest会直接结束测试,不会等待循环内的expect执行。 - 枚举遍历方式错误:
Object.keys(Status)会遍历枚举的键(如果是TypeScript枚举,还会包含反向映射的字符串键),可能导致遍历到非预期的枚举值。 - 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
相关产品推荐
相关产品推荐

