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

测试用例执行时fetch未被调用问题排查求助

问题:测试getResource函数时fetch未被正确调用的排查与解决

我正在为名为getResource的函数编写测试用例,函数代码如下:

export function getResource(uri: string, callback: Function, isJson: boolean): void {
  fetch(uri)
    .then((res) => (isJson ? res.json() : res.text()))
    .then(
      (result) => {
        callback({ isSuccessful: true, data: result });
      },
      (error) => {
        callback({ isSuccessful: false, error: error });
      }
    );
}

对应的测试用例代码:

global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () =>
      Promise.resolve({
        isSuccessful: true,
        data: { res: [] },
      }),
  })
) as jest.Mock;

describe("getResource()", () => {
  it("should call the callback function with the obj", () => {
    const mockCallback = jest.fn();
    getResource("/dummy_endpoint", mockCallback, true);
    expect(getResource).toBeCalledWith("/dummy_endpoint", mockCallback, true);
    expect(fetch).toHaveBeenCalledWith("/dummy_endpoint");
    // expect(mockCallback.mock.calls.length).toBe(1);
  });
});

执行测试时触发错误,提示fetch未被传入URI参数调用,希望得到问题分析和解决办法。


解决方案

核心原因:异步代码未等待执行

getResource内部是基于Promise的异步逻辑,但测试中是同步执行断言的——调用getResource后立刻检查fetch的调用情况,此时fetch的异步调用还没来得及执行,导致断言失败。

具体修复步骤:

  1. 让测试等待异步任务完成
    将测试用例的回调改为async函数,通过await Promise.resolve()等待所有微任务执行完毕,确保fetch和后续的Promise链都已执行:

    it("should call fetch with correct URI and trigger callback", async () => {
      const mockCallback = jest.fn();
      getResource("/dummy_endpoint", mockCallback, true);
      // 等待异步微任务执行完成
      await Promise.resolve();
      
      expect(fetch).toHaveBeenCalledWith("/dummy_endpoint");
      expect(mockCallback).toHaveBeenCalled();
    });
    

    也可以用done回调的方式,在mockCallback里触发断言并结束测试:

    it("should call fetch with correct URI and trigger callback", (done) => {
      const mockCallback = jest.fn(() => {
        expect(fetch).toHaveBeenCalledWith("/dummy_endpoint");
        done();
      });
      getResource("/dummy_endpoint", mockCallback, true);
    });
    
  2. 修正无效断言
    原测试里的expect(getResource).toBeCalledWith(...)是错误的——getResource是直接调用的普通函数,不是jest mock函数,这个断言没有意义,直接删除即可。

  3. 优化mock返回值(可选)
    原mock中json返回的结构和getResource最终传给callback的结构重复了,实际getResource会自己包装{isSuccessful: true, data: result},所以mock可以简化为直接返回业务数据:

    global.fetch = jest.fn(() =>
      Promise.resolve({
        json: () => Promise.resolve({ res: [] }),
      })
    ) as jest.Mock;
    

最终完整测试用例

global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ res: [] }),
  })
) as jest.Mock;

describe("getResource()", () => {
  it("should call fetch with correct URI and pass success data to callback", async () => {
    const mockCallback = jest.fn();
    getResource("/dummy_endpoint", mockCallback, true);
    
    await Promise.resolve();
    
    expect(fetch).toHaveBeenCalledExactlyOnceWith("/dummy_endpoint");
    expect(mockCallback).toHaveBeenCalledWith({
      isSuccessful: true,
      data: { res: [] }
    });
  });
});

内容的提问来源于stack exchange,提问作者Amrendra Nath

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:05:24