如何在Jest中Mock内部实例化的类方法完成单元测试?
解决Jest Mock内部实例化类方法的问题
当被测试服务内部自行实例化依赖类时,直接使用spyOn或普通jest.mock无法生效,因为新创建的实例不会关联到你之前mock的对象。下面是两种可行的解决方案:
方案一:Mock整个依赖类模块
通过jest.mock替换整个依赖模块的导出,让被测试代码中new ExampleService()得到的是我们预设的mock实例。
示例代码
// 先mock ExampleService模块,必须在import之前调用 jest.mock('./example.service', () => { return { ExampleService: jest.fn().mockImplementation(() => ({ // 预设findUsers的返回值,匹配Promise<Users[]>类型 findUsers: jest.fn().mockResolvedValue([ { id: 1, isHomeOwner: true }, { id: 2, isHomeOwner: false } ]) })) }; }); import { ToBeTestedService } from './toBeTested.service'; import { ExampleService } from './example.service'; // 类型断言,方便后续操作mock对象 const MockExampleService = ExampleService as jest.Mock; describe('ToBeTestedService', () => { let testedService: ToBeTestedService; beforeEach(() => { // 重置mock状态,避免测试用例间污染 MockExampleService.mockClear(); testedService = new ToBeTestedService(); }); it('筛选出所有房主用户', async () => { const result = await testedService.findHomeOwners(); // 验证findUsers方法被调用 expect(MockExampleService.mock.instances[0].findUsers).toHaveBeenCalled(); // 验证结果符合预期 expect(result).toEqual([{ id: 1, isHomeOwner: true }]); }); it('处理空用户列表的情况', async () => { // 给当前测试用例单独设置mock返回值 MockExampleService.mockImplementation(() => ({ findUsers: jest.fn().mockResolvedValue([]) })); const result = await testedService.findHomeOwners(); expect(result).toEqual([]); }); });
方案二:SpyOn依赖类的原型方法
当你用jest.mock自动mock整个模块后,可以通过spyOn该类的原型方法,让所有新实例都使用mock实现。
示例代码
// 自动mock ExampleService模块 jest.mock('./example.service'); import { ToBeTestedService } from './toBeTested.service'; import { ExampleService } from './example.service'; describe('ToBeTestedService', () => { let testedService: ToBeTestedService; let mockFindUsers: jest.Mock; beforeEach(() => { // 创建mock方法,指定返回类型 mockFindUsers = jest.fn().mockResolvedValue([{ id: 1, isHomeOwner: true }]); // SpyOn原型上的findUsers方法,替换为mock实现 jest.spyOn(ExampleService.prototype, 'findUsers').mockImplementation(mockFindUsers); testedService = new ToBeTestedService(); }); afterEach(() => { // 恢复所有mock,避免影响其他测试 jest.restoreAllMocks(); }); it('正确返回房主用户', async () => { const result = await testedService.findHomeOwners(); expect(mockFindUsers).toHaveBeenCalled(); expect(result).toEqual([{ id: 1, isHomeOwner: true }]); }); });
关键注意事项
jest.mock必须在模块import之前调用,否则原模块会先被加载,mock无法生效。- TypeScript环境下需要用
jest.Mock类型断言处理mock对象,避免类型报错。 - 测试用例之间要重置或恢复mock状态,防止测试污染。
内容的提问来源于stack exchange,提问作者quefro
相关产品推荐
相关产品推荐

