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
相关产品推荐
相关产品推荐

