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

如何测试嵌套Promise中api.send函数的第二层调用?

多次调用同个异步方法的Mock配置方案

核心问题说明

你当前的写法存在两个问题:

  1. 链式调用and.returnValue会直接覆盖前一次的返回值配置,最终所有调用只会返回最后设置的Promise,无法实现两次调用返回不同结果
  2. 业务代码是Promise异步链式逻辑,测试默认不会等待异步执行完成就运行断言,会导致第二个api.send还没触发就结束测试

修正方案

1. 用顺序返回值配置两次调用的返回结果

Jest/Jasmine的Spy提供了and.returnValues方法,传入的参数会按调用顺序依次返回,刚好适配你两次调用需要返回不同结果的场景。

2. 等待异步逻辑执行完成再断言

将测试用例改为async函数,调用完目标方法后清空微任务队列,保证所有Promise回调执行完成再运行断言。

修正后的测试代码示例

describe('itemToForm()', () => {
  // 每次测试跑完清除所有spy,避免用例之间互相影响
  afterEach(() => {
    jest.restoreAllMocks();
  });

  it('should call api.send first with ES lang parameter', () => {
    let item = { id: 1, name: 'test' };
    component.component = 'Events';
    let resEsp = {
      data: [
        { id: 1, name: 'test1' },
        { id: 2, name: 'test2' },
        { id: 3, name: 'test3' }
      ]
    };
    component.item = item;

    let spy1 = spyOn(api, 'send').and.returnValue(Promise.resolve(resEsp));
    component.itemToForm();

    expect(spy1).toHaveBeenCalled();
    expect(spy1).toHaveBeenCalledTimes(1);
    expect(spy1).toHaveBeenCalledWith('Events', 'get', { lang: 'ES', filter: { id: 1 } });
  });

  it('should call api.send twice with correct ES and EN parameters', async () => {
    component.component = 'Events';
    // 第一次调用返回的西语数据
    const resEsp = {data: [{ id: 1, name: '测试西语名' }, { id: 2, name: 'test2' }, { id: 3, name: 'test3' }]};
    // 第二次调用返回的英语数据
    const resEng = {data: [{ id: 1, name: 'Test English Name' }, { id: 2, name: 'test2' }, { id: 3, name: 'test3' }]};
    component.item = { id: 1, name: '初始名' };

    // 按调用顺序配置返回值,第一次返回resEsp,第二次返回resEng
    const spySend = spyOn(api, 'send').and.returnValues(
      Promise.resolve(resEsp),
      Promise.resolve(resEng)
    );
    // 监听setForm调用,可选,用于验证后续逻辑
    const spySetForm = spyOn(component, 'setForm');

    component.itemToForm();
    // 清空微任务队列,等待所有Promise回调执行完成
    await Promise.resolve();

    // 校验总共调用2次send
    expect(spySend).toHaveBeenCalledTimes(2);
    // 校验第一次调用参数(西语请求)
    expect(spySend).toHaveBeenNthCalledWith(1, 'Events', 'get', { lang: 'ES', filter: { id: 1 } });
    // 校验第二次调用参数(英语请求,id取第一次返回结果的id)
    expect(spySend).toHaveBeenNthCalledWith(2, 'Events', 'get', { lang: 'EN', filter: { id: 1 } });
    // 校验最终setForm被调用,可选
    expect(spySetForm).toHaveBeenCalled();
  });
});

内容的提问来源于stack exchange,提问作者David Angarita

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:57:02