如何使用Jest Mock方法内部创建的DataHandler类?
如何正确Mock Jest中内部实例化的DataHandler类
我在测试ProductDatatHandler类的process方法时,遇到了无法Mock内部创建的DataHandler实例的问题,报错「TypeError: DataHandler is not a constructor」。原代码中process方法会通过LookupService获取处理器,然后实例化DataHandler并调用其insert方法。
原Mock代码错误在于没有正确模拟DataHandler这个类的构造函数,而是直接导出了insert方法,导致代码执行new DataHandler()时失败。
正确的Mock写法
要正确Mock内部实例化的类,需要让Jest模拟整个模块,导出一个Mock构造函数,并且该构造函数返回的实例包含Mock的insert方法:
jest.mock('./product-handlers/data-handler', () => { // 定义Mock的insert方法 const mockInsert = jest.fn(); return { __esModule: true, // 导出Mock的DataHandler构造函数,实例化时返回带有insert方法的对象 DataHandler: jest.fn().mockImplementation(() => ({ insert: mockInsert })) }; });
测试中的验证逻辑
在测试用例中,你可以导入Mock后的DataHandler,并验证它的实例化和方法调用情况:
import { DataHandler } from './product-handlers/data-handler'; import { ProductDatatHandler } from './product-data-handler'; import { LookupService } from './service/lookup'; // 类型断言,将DataHandler转为Jest Mock类型 const MockDataHandler = DataHandler as jest.Mock; describe('ProductDatatHandler', () => { let productHandler: ProductDatatHandler; let mockLookupService: jest.Mocked<LookupService>; beforeEach(() => { // 每次测试前重置Mock状态 MockDataHandler.mockClear(); const mockInsert = MockDataHandler.mock.results[0]?.value?.insert; if (mockInsert) mockInsert.mockClear(); // 模拟LookupService的返回值 mockLookupService = { getProductHandlerForType: jest.fn().mockResolvedValue({}) }; productHandler = new ProductDatatHandler(); }); it('实例化DataHandler并调用insert方法(当data存在value时)', async () => { const testData = { type: 'test-type', value: 'test-value' } as ProductMetadata; await productHandler.process(testData, mockLookupService); // 验证DataHandler被正确实例化,且传入了处理器参数 expect(MockDataHandler).toHaveBeenCalledWith(expect.any(Object)); // 验证insert方法被调用,且传入了测试数据 const mockInsert = MockDataHandler.mock.results[0].value.insert; expect(mockInsert).toHaveBeenCalledWith(testData); }); });
错误原因说明
你之前的Mock代码直接导出了insert方法,但原代码中是通过new DataHandler()来创建实例的——此时模块导出的DataHandler应该是一个构造函数,而不是普通方法。之前的写法导致Jest替换后的DataHandler不是构造函数,所以执行new操作时抛出类型错误。
内容的提问来源于stack exchange,提问作者BreenDeen
相关产品推荐
相关产品推荐

