如何在Jest中测试Promise?请求调用断言不符问题求助
Jest测试时axios请求调用次数不符合预期的问题解决
问题根源
- mock对象错误:你直接mock了
axios.post和axios.get,但业务代码中所有请求都是通过axios.create()创建的实例来调用post/get方法,全局axios的方法mock不会作用于这些实例,导致实例的请求没有被统计到。 - 异步流程未完全等待:
init函数中Promise.any([getPromise1, getPromise2])没有被await,虽然get()返回了init()的Promise,但init()内部的promises异步链并没有被等待,导致测试在部分异步操作完成前就执行了断言。
修正方案
步骤1:正确mock axios.create
修改测试代码,mockaxios.create使其返回包含mock post/get方法的对象,这样所有通过create创建的实例的请求都会被追踪:
// 先重置所有mock jest.mock('axios'); // 创建mock的实例方法 const mockAxiosInstance = { post: jest.fn().mockResolvedValue({ status: 200, data: { data: '123' } }), get: jest.fn().mockResolvedValue({ status: 200, data: { id: '123' } }) }; // 让axios.create返回这个mock实例 axios.create.mockReturnValue(mockAxiosInstance);
步骤2:确保等待所有异步操作完成
修改业务代码中的init函数,await住Promise.any的结果,这样get()返回的Promise会等待所有相关异步流程完成:
async function init() { try { const result = await Promise.any([getPromise1, getPromise2]); return result; } catch (error) { return error; } }
修正后的测试断言
现在断言需要针对mock的实例方法,同时保留axios.create的调用次数校验:
await get(); expect(axios.create).toBeCalledTimes(3); expect(mockAxiosInstance.post).toBeCalledTimes(1); // 对应getToken里的POST请求 expect(mockAxiosInstance.get).toBeCalledTimes(2); // 对应两个GET请求
额外优化建议
避免使用new Promise(async (resolve, reject) => {})这种反模式写法——async函数本身就返回Promise,直接用async函数代替即可,比如把getPromise1改成:
const getPromise1 = async () => { const token = await getToken(); const http = axios.create({ headers: { Authorization: `Token ${token}` } }); const response = await http.get("/endpoint-2"); return response.data; };
这样代码更简洁,也能避免Promise executor中使用async带来的潜在问题。
内容的提问来源于stack exchange,提问作者Denilson Raimundo
相关产品推荐
相关产品推荐

