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

Jest模拟具名导出时抛出TypeError: ...is not a function问题求助

问题1:jest.mock写法导致createAsync不是函数的原因及修复

你当前的写法存在变量提升问题:jest.mock会被自动提升到文件最顶部执行,此时你定义的mockCreate还未初始化,所以MyIconFactory的mock实现返回的createAsync是undefined,调用自然会报错。

修复方案有两种:

方案1:在mock内部定义mock函数

把mockCreate的定义放到jest.mock的回调里,避免变量提升问题:

import { Icon, MyIconFactory } from "IconFactory";
import { createIcon } from "Client";

jest.mock("IconFactory", () => {
  const originalModule = jest.requireActual("IconFactory");
  const mockIcon = new originalModule.Icon();
  const mockCreate = jest.fn().mockResolvedValue(mockIcon);

  return {
    __esModule: true,
    ...originalModule,
    MyIconFactory: jest.fn().mockImplementation(() => ({
      createAsync: mockCreate
    })),
  };
});

it("should create icon correctly", async () => {
  const entity = new Entity();
  await createIcon(entity);
  
  // 断言MyIconFactory被实例化
  expect(MyIconFactory).toHaveBeenCalled();
  // 断言createAsync被传入正确参数调用
  expect(MyIconFactory.mock.results[0].value.createAsync).toHaveBeenCalledWith(entity);
});

方案2:使用jest.doMock避免变量提升

如果需要在测试用例中单独控制mock行为,可以用jest.doMock(不会自动提升),并动态导入业务模块:

import { Icon, MyIconFactory } from "IconFactory";

const mockCreate = jest.fn().mockResolvedValue(new Icon());

// 用doMock避免自动提升,确保mockCreate已初始化
jest.doMock("IconFactory", () => {
  const originalModule = jest.requireActual("IconFactory");
  return {
    __esModule: true,
    ...originalModule,
    MyIconFactory: jest.fn().mockImplementation(() => ({
      createAsync: mockCreate
    })),
  };
});

// 动态导入Client,确保使用mock后的模块
const { createIcon } = await import("Client");

it("should create icon correctly", async () => {
  const entity = new Entity();
  await createIcon(entity);
  
  expect(mockCreate).toHaveBeenCalledWith(entity);
});

问题2:jest.spyOn无效的原因及修复

你尝试的jest.spyOn(IconFactory.prototype)是错误的:IconFactory是接口,不是可实例化的类,它没有prototype属性。你需要spy的是实际被实例化的MyIconFactory的原型:

import { MyIconFactory, Icon } from "IconFactory";
import { createIcon } from "Client";

it("should create icon correctly", async () => {
  // Spy on MyIconFactory原型上的createAsync方法
  const mockCreate = jest.spyOn(MyIconFactory.prototype, "createAsync")
    .mockResolvedValue(new Icon());

  const entity = new Entity();
  await createIcon(entity);
  
  expect(mockCreate).toHaveBeenCalledWith(entity);
  
  // 测试结束后恢复原始实现
  mockCreate.mockRestore();
});

核心逻辑:Client中创建的是MyIconFactory的实例,它的方法来自MyIconFactory.prototype,spy这个对象的方法才能覆盖原始实现。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 22:36:27