You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 04:03:35