Typescript+NestJS+Jest如何mock服务调用的外部公共共享函数
你可以直接通过Jest的模块Mock能力实现需求,不需要修改任何业务代码,前提是ReadFileContents是作为ES模块的导出成员使用的(也就是你在my.service.ts里是通过import语句引入的该函数),以下是具体实现方案:
方案1:单用例灵活Mock(推荐,适配多场景测试需求)
该方案可以针对单个测试用例自定义ReadFileContents的返回值/抛出异常,不会影响其他用例的执行:
- 首先在测试文件顶部导入
ReadFileContents所在的完整模块:
import { Test, TestingModule } from '@nestjs/testing'; import { MyService } from './my.service'; // 替换为你实际存放ReadFileContents的文件路径 import * as fileUtils from './file.utils';
- 在测试用例中使用
jest.spyOn监听该方法,自定义返回行为:
// 测试读取文件抛出异常的场景 it('should handle exceptions when reading missing .hdr file', async () => { // Mock ReadFileContents调用时抛出异常 const mockReadFile = jest.spyOn(fileUtils, 'ReadFileContents') .mockRejectedValue(new Error('文件不存在')); // 给服务的私有属性赋值(如果是private属性TS报错,用[]索引访问即可绕过校验) service['Directory_'] = '/test/dir'; service['BaseName_'] = 'test-file'; // 断言GetData方法返回符合预期的错误结果 await expect(service.GetData()).rejects.toMatchObject({ StatusCode: 404, Contents: 'File not found: test-file in /test/dir' }); // 可选:验证mock方法被调用时传入的参数符合预期 expect(mockReadFile).toHaveBeenCalledWith('/test/dir', 'test-file'); // 清理mock,避免影响其他测试用例 mockReadFile.mockRestore(); }); // 测试正常读取文件的场景 it('should return correct result when files exist', async () => { const mockReadFile = jest.spyOn(fileUtils, 'ReadFileContents') // 第一次调用(读取正文文件)返回自定义内容 .mockResolvedValueOnce('测试文本内容') // 第二次调用(读取.err状态文件)返回状态码文本 .mockResolvedValueOnce('201'); service['Directory_'] = '/test/dir'; service['BaseName_'] = 'test-file'; const result = await service.GetData(); expect(result.Contents).toBe('测试文本内容'); expect(result.StatusCode).toBe(201); // 验证两次调用的参数都符合预期 expect(mockReadFile).toHaveBeenNthCalledWith(1, '/test/dir', 'test-file'); expect(mockReadFile).toHaveBeenNthCalledWith(2, '/test/dir', 'test-file.err'); mockReadFile.mockRestore(); });
方案2:全局Mock当前测试文件所有调用
如果当前测试文件所有用例都需要MockReadFileContents,可以在测试文件顶部直接全局Mock整个模块:
// 要放在导入fileUtils的语句之前 jest.mock('./file.utils', () => ({ ReadFileContents: jest.fn() })); import * as fileUtils from './file.utils'; // 后续用例不需要再写jest.spyOn,直接修改mock的返回值即可 it('test xxx', async () => { (fileUtils.ReadFileContents as jest.Mock).mockResolvedValue('自定义内容'); // 执行测试逻辑... })
补充说明
如果ReadFileContents是默认导出的模块,只需要把jest.spyOn的第二个参数改为'default'即可:
jest.spyOn(fileUtils, 'default').mockResolvedValue('xxx')
内容的提问来源于stack exchange,提问作者Steven Scott
相关产品推荐
相关产品推荐

