如何使用Jest测试TypeScript中返回void的重试函数?
问题原因与解决方案
核心错误原因
toHaveBeenCalledTimes、toHaveBeenCalled这类Jest断言仅支持被Jest包装过的mock/spy函数,直接对普通函数调用这类断言自然会抛出类型不匹配的错误- 现有测试逻辑没有模拟函数抛出错误的场景,无法触发重试分支
- 原
retryNTimes未处理异步函数场景,如果传入像TestUser这类async函数,try/catch无法捕获异步抛出的错误,重试逻辑不会生效
前置代码调整
先修改retry.ts,补全缺失的常量定义、导出,同时优化异步兼容:
// 补全重试次数常量定义,导出方便测试用 export const MAX_NUMBER_OF_RETRIES = 3; // 优化支持异步函数的重试逻辑 export const retryNTimes = async (retryFunction: Function) => { let retry = 0; while(retry < MAX_NUMBER_OF_RETRIES){ try { await retryFunction() break } catch (err) { console.log(`Try ${retry}: ${err}`) retry += 1 } } } export type User = { userId: string } export const TestUser = async ({ userId, }:User) => { console.log(`userid : ${userId} `) }
测试文件正确写法
修改retry.test.ts如下:
import { retryNTimes, MAX_NUMBER_OF_RETRIES } from './retry'; describe('retry Function', () => { // 每个测试用例执行前重置mock状态,避免用例之间互相影响 beforeEach(() => { jest.clearAllMocks(); }); test('被调用函数首次执行成功时,仅调用1次,无重试', async () => { // 创建成功执行的mock函数 const mockSuccessFn = jest.fn().mockResolvedValue(undefined); await retryNTimes(mockSuccessFn); expect(mockSuccessFn).toHaveBeenCalledTimes(1); }); test('被调用函数第N次执行成功时,总调用次数为N', async () => { let callCount = 0; // 模拟前1次调用抛错,第2次调用成功 const mockFn = jest.fn(() => { callCount++; if (callCount < 2) { throw new Error('模拟调用失败'); } return Promise.resolve(); }); await retryNTimes(mockFn); expect(mockFn).toHaveBeenCalledTimes(2); }); test('被调用函数持续报错时,最多重试MAX_NUMBER_OF_RETRIES次', async () => { // 创建始终抛出错误的mock函数 const mockFailFn = jest.fn().mockRejectedValue(new Error('模拟调用始终失败')); await retryNTimes(mockFailFn); expect(mockFailFn).toHaveBeenCalledTimes(MAX_NUMBER_OF_RETRIES); }); })
执行测试命令即可看到所有用例通过,所有重试场景都得到了验证。
内容的提问来源于stack exchange,提问作者puggyman210
相关产品推荐
相关产品推荐

