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

Jest中mockResolvedValue失效:异步上下文函数返回undefined

问题根源

你的测试报错是因为**main.ts在模块加载阶段就自动执行了registerCommands()**,而此时测试代码里的mockResolvedValue还没来得及设置——Jest的模块级jest.mock只会创建一个空的mock函数(默认返回undefined),it块里的mock配置是在模块加载之后才执行的,所以第一次执行registerCommands()时,loadCommands返回的是undefined,触发了错误。

解决方案

你有两种可行的修复方向:

方向1:修改源码,移除模块顶层的自动调用

把registerCommands()的执行逻辑从模块顶层移出,交给外部调用,这样测试可以完全控制执行时机:

修改main.ts:

import { loadCommands } from "./load-commands";

export async function registerCommands() {
  const commandRegistry = await loadCommands();
  if (!commandRegistry) throw new Error("commandRegistry is undefined");

  commandRegistry.forEach((command) => command.register());
}

// 移除自动调用,改为导出初始化函数让外部触发
export function initCommands() {
  registerCommands();
}

// 或者在实际业务代码中,由入口文件调用initCommands()

对应的测试代码可以保持原有逻辑,因为现在registerCommands()只会在测试主动调用时执行:

import { registerCommands } from "./main";
import { loadCommands } from "./load-commands";
import { jest } from "@jest/globals";

jest.mock("./load-commands", () => ({
  loadCommands: jest.fn(),
}));

describe("registerCommands", () => {
  it("should load commands and call register on each", async () => {
    const mockCommand = { register: jest.fn(), taskName: "Mock Command" };
    (loadCommands as jest.Mock).mockResolvedValue([mockCommand]);

    await registerCommands();

    expect(loadCommands).toHaveBeenCalledTimes(1);
    expect(mockCommand.register).toHaveBeenCalled();
  });
});

方向2:不修改源码,用动态导入控制模块加载时机

如果无法修改main.ts的结构,就用Jest的动态导入功能,确保在设置好mock之后再加载main模块:

修改测试代码:

import { jest } from "@jest/globals";

describe("registerCommands", () => {
  // 每次测试前重置模块,避免缓存影响
  beforeEach(() => {
    jest.resetModules();
  });

  it("should load commands and call register on each", async () => {
    const mockCommand = { register: jest.fn(), taskName: "Mock Command" };
    
    // 先设置好完整的mock
    jest.mock("./load-commands", () => ({
      loadCommands: jest.fn().mockResolvedValue([mockCommand]),
    }));

    // 动态导入main模块,此时mock已经生效
    const { registerCommands } = await import("./main");
    await registerCommands();

    const { loadCommands } = await import("./load-commands");
    expect(loadCommands).toHaveBeenCalledTimes(1);
    expect(mockCommand.register).toHaveBeenCalled();
  });
});

这种方式通过jest.resetModules()清除模块缓存,再用动态导入确保mock配置完成后才加载main.ts,避免了模块顶层自动执行的问题。

内容的提问来源于stack exchange,提问作者I'll-Be-Back

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:40:02