测试用例执行时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的异步调用还没来得及执行,导致断言失败。
具体修复步骤:
让测试等待异步任务完成
将测试用例的回调改为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); });修正无效断言
原测试里的expect(getResource).toBeCalledWith(...)是错误的——getResource是直接调用的普通函数,不是jest mock函数,这个断言没有意义,直接删除即可。优化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
相关产品推荐
相关产品推荐

