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

Jest中mock函数返回的嵌套get方法时spyOn报错如何解决

问题根因

报错的核心原因有两个:

  1. jest.mock的工厂返回值结构错误:你写的mock工厂返回的函数执行后返回了带default属性的对象,但业务代码是默认导入axiosInstanceWrapper,导入的变量本身就是mock工厂返回的函数,调用该函数应该直接返回带get方法的实例,不需要嵌套default层。
  2. spyOn的监听目标完全错误:get是axiosInstanceWrapper()执行后返回的实例上的方法,既不挂载在axiosInstanceWrapper函数本身,也不存在于它的default属性上,直接对axiosInstanceWrapper.get做监听自然会拿到undefined。
正确实现方案

方案1:直接在mock模块时定义可复用的mock方法(推荐)

先把实例上的get抽成独立的mock函数引用,方便后续设置返回值、做调用断言,代码示例:

import axiosInstanceWrapper from './axios-instance-wrapper';

// 提前定义mock的get方法,方便后续用例内操作
const mockGet = jest.fn();
// 修正mock工厂的返回结构
jest.mock('./axios-instance-wrapper', () => {
  // 默认导入的axiosInstanceWrapper就是这个函数,调用后直接返回带get的mock实例
  return jest.fn(() => ({
    get: mockGet
  }));
});

// 每个用例执行前清空mock记录,避免用例间互相干扰
beforeEach(() => {
  jest.clearAllMocks();
});

test('正确mock api.get返回值', () => {
  // 设置get方法的resolve返回值
  mockGet.mockResolvedValue({
    data: {
      customer: {
        subscriptionContracts: [],
        pageInfo: {
          hasNextPage: false,
          hasPreviousPage: false,
        }
      }
    }
  });

  // 此处执行业务逻辑,例如调用封装了api.get的业务函数
  // const result = await 你的业务方法();

  // 可额外断言get的入参是否符合预期
  // expect(mockGet).toHaveBeenCalledWith(MY_URL, myParams);
});

方案2:拿到mock实例后用spyOn监听

如果你更习惯用spyOn的写法,需要先拿到axiosInstanceWrapper执行返回的实例,再对实例上的get做监听:

import axiosInstanceWrapper from './axios-instance-wrapper';

jest.mock('./axios-instance-wrapper', () => {
  return jest.fn(() => ({
    get: () => {} // 先给一个空函数占位,spyOn才能挂载
  }));
});

test('spyOn写法实现', () => {
  // 先拿到mock返回的实例
  const mockApiInstance = axiosInstanceWrapper({});
  // 对实例上的get做监听和返回值mock
  const getSpy = jest.spyOn(mockApiInstance, 'get').mockResolvedValue({
    data: {
      customer: {
        subscriptionContracts: [],
        pageInfo: {
          hasNextPage: false,
          hasPreviousPage: false,
        }
      }
    }
  });

  // 后续执行业务逻辑、做断言即可
});
注意事项

如果你的业务代码里const api = axiosInstanceWrapper({})是写在模块顶层的,需要注意mock的生效时机:必须在导入业务模块之前完成mock注册,否则业务模块初始化时拿到的是真实的axiosInstanceWrapper,会导致mock失效。遇到这种场景可以在每个用例前重置模块,再动态导入业务模块:

beforeEach(() => {
  jest.resetModules();
  jest.clearAllMocks();
});

test('顶层初始化api的场景处理', () => {
  mockGet.mockResolvedValue(/* 你需要的返回值 */);
  // 重置模块后再动态导入业务模块,会自动使用已mock的axiosInstanceWrapper初始化api
  const businessModule = require('./你的业务文件路径');
  // 执行业务逻辑完成测试
  // await businessModule.你的业务方法();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 10:18:43