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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:30:05