如何在Jest中mock类 测试时不触发真实JSON文件写入
Jest 单元测试 mock 文件写入实现方案
核心目标是拦截fs.writeFile的真实调用,全程不操作本地磁盘文件,同时保证测试逻辑能覆盖方法的所有分支。
前置准备
不需要安装额外依赖,Jest原生支持对Node内置模块的mock能力,只需要在测试文件中按以下步骤配置即可。
步骤1:全局mock fs模块
在测试文件最顶部声明对fs模块的mock,Jest会自动把fs的所有方法替换为可追踪的mock空函数,所有文件读写操作都不会落到真实磁盘:
const fs = require('fs'); const YourPostClass = require('./你的类文件实际路径'); // 替换为你存放addPost方法的类的引入路径 // 这行代码会被Jest自动提升到文件最顶部执行,保证所有fs引用都是mock版本 jest.mock('fs');
注意:不要在测试代码里手动引入真实的
./json/data.json文件,所有测试数据都在测试用例内构造,避免和本地真实文件产生耦合。
步骤2:测试用例执行前重置状态
因为mock函数、类的静态属性会在多个测试用例之间共享状态,每个用例跑之前要重置状态,避免用例之间互相干扰:
beforeEach(() => { // 清空所有fs mock的调用记录、自定义返回值 jest.resetAllMocks(); // 重置类的静态allPosts属性为测试初始值,不要用真实文件读取的内容 YourPostClass.allPosts = []; });
步骤3:编写测试用例
核心校验三个维度:方法返回值符合预期、内存中的帖子列表正确更新、文件写入方法被正确参数调用(但不真实执行写入):
describe('静态方法addPost测试', () => { it('应该正确生成新帖子、触发写入逻辑但不修改本地文件', () => { // 构造测试入参 const testInput = { title: '测试帖子标题', content: '测试帖子正文', tag: 'test' }; // 调用被测方法 const newPost = YourPostClass.addPost(testInput); // 校验返回的新帖子结构正确 expect(newPost).toEqual({ id: 1, ...testInput }); // 校验内存中的帖子列表已经追加新内容 expect(YourPostClass.allPosts).toHaveLength(1); expect(YourPostClass.allPosts[0]).toEqual(newPost); // 校验fs.writeFile的调用参数完全符合预期 const expectedFileContent = JSON.stringify(YourPostClass.allPosts, null, 2); expect(fs.writeFile).toHaveBeenCalledTimes(1); expect(fs.writeFile).toHaveBeenCalledWith( './json/data.json', expectedFileContent, expect.any(Function) // 匹配方法传入的回调函数 ); // 可选:覆盖写入报错分支 const writeCallback = fs.writeFile.mock.calls[0][2]; expect(() => writeCallback(new Error('写入失败'))).toThrow('写入失败'); }); it('连续插入帖子时ID应该正确自增', () => { // 预置初始帖子数据 YourPostClass.allPosts = [{id: 1, title: '第一个帖子'}]; const secondPost = YourPostClass.addPost({title: '第二个帖子'}); expect(secondPost.id).toBe(2); expect(YourPostClass.allPosts).toHaveLength(2); }); });
扩展场景适配
如果你的类中allPosts属性是初始化时通过fs.readFile/fs.readFileSync从json文件读取的,只需要在beforeEach中给对应的读方法mock返回测试数据即可,完全脱离真实文件依赖:
beforeEach(() => { jest.resetAllMocks(); // mock读文件返回预置测试数据 fs.readFileSync.mockReturnValue(JSON.stringify([ {id: 1, title: '预置测试帖子'} ])); // 如果是异步的readFile,就用mockImplementation触发回调传值 // fs.readFile.mockImplementation((path, options, cb) => cb(null, JSON.stringify([{id:1}]))); YourPostClass.allPosts = JSON.parse(fs.readFileSync('./json/data.json')); });
执行测试时全程不会修改本地真实的./json/data.json文件,所有文件操作都在mock层被拦截。
内容的提问来源于stack exchange,提问作者Hanibal Brhanu
相关产品推荐
相关产品推荐

