如何在Jest中测试嵌套Promise?函数传参测试遇阻
搞定Jest测试接收数组/Promise参数的函数问题
嘿,我来帮你解决这个测试难题!首先看你贴的saveItems代码有点不完整,我先补全一个符合你描述逻辑的版本(毕竟要接收数组或Promise参数嘛),然后一步步给你写验证逻辑的测试用例:
// sendItems.js 补全后的合理代码 import axios from 'axios'; export const saveItems = (items) => { // 统一转成Promise,不管传入的是数组还是Promise const resolvedItems = Promise.resolve(items); return resolvedItems.then(data => { return axios({ url: '/stuff/graphql', method: 'POST', // 假设是POST请求,你可以根据实际情况调整 data: data }); }); };
第一步:Mock Axios
测试的时候绝对不能发真实请求,所以我们先用Jest把axios给mock掉,这样既能拦截请求,还能断言它有没有被正确调用:
// sendItems.test.js import axios from 'axios'; import { saveItems } from './sendItems'; // 自动mock axios的所有方法 jest.mock('axios');
第二步:测试传入数组的场景
这个场景比较直接,就是验证函数把数组直接传给axios就行:
test('传入数组时,直接把数组传给axios', async () => { const testArray = [{ id: 1, name: 'test1' }, { id: 2, name: 'test2' }]; // 模拟axios请求成功的响应 axios.mockResolvedValueOnce({ data: '保存成功' }); await saveItems(testArray); // 断言axios被调用,且参数里的data就是我们传入的数组 expect(axios).toHaveBeenCalledWith(expect.objectContaining({ url: '/stuff/graphql', data: testArray })); });
第三步:测试传入Promise的场景
这里要验证两个点:一是函数确实等待了Promise解析,二是axios最终拿到的是Promise解析后的值。
简单验证版
直接用原生Promise来测试,看axios是否拿到了解析后的数据:
test('传入Promise时,先等待解析再传给axios', async () => { const resolvedData = [{ id: 3, name: 'test3' }]; const mockPromise = Promise.resolve(resolvedData); axios.mockResolvedValueOnce({ data: '保存成功' }); await saveItems(mockPromise); // 断言axios接收到的是Promise解析后的数据 expect(axios).toHaveBeenCalledWith(expect.objectContaining({ data: resolvedData })); });
严谨验证版(确认then被调用)
如果想更严谨地确认函数确实调用了Promise的then方法,我们可以手动创建一个带mock then的对象:
test('传入Promise时,确实会调用then方法等待解析', async () => { const mockThen = jest.fn((callback) => callback('解析后的数据')); const mockPromise = { then: mockThen }; axios.mockResolvedValueOnce({ data: '保存成功' }); await saveItems(mockPromise); // 断言then方法被调用了 expect(mockThen).toHaveBeenCalled(); // 断言axios拿到的是then回调返回的值 expect(axios).toHaveBeenCalledWith(expect.objectContaining({ data: '解析后的数据' })); });
额外:测试错误场景(可选)
如果需要测试Promise拒绝的情况,也可以加这个用例:
test('当传入的Promise拒绝时,函数也会拒绝', async () => { const testError = new Error('Promise执行失败'); const mockPromise = Promise.reject(testError); // 断言函数会抛出对应的错误 await expect(saveItems(mockPromise)).rejects.toThrow(testError); // 此时axios不应该被调用 expect(axios).not.toHaveBeenCalled(); });
内容的提问来源于stack exchange,提问作者Max Millington
相关产品推荐
相关产品推荐

