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

Jest模拟时模块引入顺序导致api为undefined的原因

问题:Jest模拟因模块引入顺序导致失效的原因

当const { findFoo } = require("./foo");留在test.js当前位置时,foo.js内的api会打印为undefined;但将其移到const spy =代码行下方后,功能正常。请问为何这种引入顺序下Jest的模拟无法生效?


foo.js

/* eslint-disable camelcase */
const { createApiInstance } = require("./../utils/api");

const api = createApiInstance()

async function findFoo(name) {
  console.log({ api });
  const res = await api({
    method: "GET",
    url: `/bar`,
  })
}

module.exports = { findFoo }

utils.js

const axios = require("axios");

const createApiInstance = (params) => axios.create();

module.exports = {
  createApiInstance,
};

test.js

const apiWrapper = require("./../utils/api");
jest.mock("./../utils/api");

const { findFoo } = require("./foo");

describe("Foo", () => {
  describe("findFoo", () => {
    it("foos", async () => {
      const spy = jest
        .spyOn(apiWrapper, "createApiInstance")
        .mockImplementation(() => Promise.resolve(jest.fn()));

      const res = await findFoo("foo");
      console.log(res);
      spy.mockRestore();
    });
  });
});

原因解释

核心问题出在模块加载时机和Jest模拟的生效顺序上:

  1. jest.mock("./../utils/api")会自动创建一个空的模拟对象,此时createApiInstance是一个无返回值的Jest mock函数,默认调用会返回undefined。
  2. 当你在创建spy之前就require("./foo"),foo.js会立即执行模块内的所有代码:
    • 先引入createApiInstance(此时是Jest的空mock)
    • 同步执行const api = createApiInstance(),因为mock还没被设置返回值,api直接被赋值为undefined
  3. 后续再给createApiInstance设置mockImplementation已经没用了——foo.js里的api是模块级变量,在模块加载时就已经确定值,不会重新执行赋值逻辑。

而把require("./foo")移到spy创建之后,顺序就变成:

  • 先给createApiInstance设置好带有预期返回值的mock
  • 再加载foo.js,此时执行createApiInstance()会拿到你设置的mock函数,api就能被正确赋值。

另外补充一个小问题:你当前的mock返回了Promise,但foo.js里是同步调用createApiInstance(),所以api会变成Promise对象而非可调用的函数。正确的mock应该直接返回jest函数:

const spy = jest
  .spyOn(apiWrapper, "createApiInstance")
  .mockImplementation(() => jest.fn(() => Promise.resolve({})));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:52:38