Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

mock-fs

tschaub1.5mMIT5.4.1TypeScript support: definitely-typed

A configurable mock file system. You know, for testing.

mock, fs, test, fixtures, file system, memory

readme

Build Status

mock-fs

The mock-fs module allows Node's built-in fs module to be backed temporarily by an in-memory, mock file system. This lets you run tests against a set of mock files and directories instead of lugging around a bunch of test fixtures.

Example

The code below makes it so the fs module is temporarily backed by a mock file system with a few files and directories.

const mock = require('mock-fs');

mock({
  'path/to/fake/dir': {
    'some-file.txt': 'file content here',
    'empty-dir': {/** empty directory */}
  },
  'path/to/some.png': Buffer.from([8, 6, 7, 5, 3, 0, 9]),
  'some/other/path': {/** another empty directory */}
});

When you are ready to restore the fs module (so that it is backed by your real file system), call mock.restore(). Note that calling this may be mandatory in some cases. See istanbuljs/nyc#324

// after a test runs
mock.restore();

Upgrading to version 4

Instead of overriding all methods of the built-in fs module, the library now overrides process.binding('fs'). The purpose of this change is to avoid conflicts with other libraries that override fs methods (e.g. graceful-fs) and to make it possible to work with multiple Node releases without maintaining copied and slightly modified versions of Node's fs module.

Breaking changes:

  • The mock.fs() function has been removed. This returned an object with fs-like methods without overriding the built-in fs module.
  • The object created by fs.Stats is no longer an instance of fs.Stats (though it has all the same properties and methods).
  • Lazy require() do not use the real filesystem.
  • Tests are no longer run in Node < 4.

Some of these breaking changes may be restored in a future release.

Docs

mock(config, options)

Configure the fs module so it is backed by an in-memory file system.

Calling mock sets up a mock file system with two directories by default: process.cwd() and os.tmpdir() (or os.tmpDir() for older Node). When called with no arguments, just these two directories are created. When called with a config object, additional files, directories, and symlinks are created. To avoid creating a directory for process.cwd() and os.tmpdir(), see the options below.

Property names of the config object are interpreted as relative paths to resources (relative from process.cwd()). Property values of the config object are interpreted as content or configuration for the generated resources.

Note that paths should always use forward slashes (/) - even on Windows.

options

The second (optional) argument may include the properties below.

  • createCwd - boolean Create a directory for process.cwd(). This is true by default.
  • createTmp - boolean Create a directory for os.tmpdir(). This is true by default.

Loading real files & directories

You can load real files and directories into the mock system using mock.load()

Notes

  • All stat information is duplicated (dates, permissions, etc)
  • By default, all files are lazy-loaded, unless you specify the {lazy: false} option

options

Option Type Default Description
lazy boolean true File content isn't loaded until explicitly read
recursive boolean true Load all files and directories recursively

mock.load(path, options)

mock({
  // Lazy-load file
  'my-file.txt': mock.load(path.resolve(__dirname, 'assets/special-file.txt')),

  // Pre-load js file
  'ready.js': mock.load(path.resolve(__dirname, 'scripts/ready.js'), {lazy: false}),

  // Recursively loads all node_modules
  'node_modules': mock.load(path.resolve(__dirname, '../node_modules')),

  // Creates a directory named /tmp with only the files in /tmp/special_tmp_files (no subdirectories), pre-loading all content
  '/tmp': mock.load('/tmp/special_tmp_files', {recursive: false, lazy:false}),

  'fakefile.txt': 'content here'
});

Creating files

When config property values are a string or Buffer, a file is created with the provided content. For example, the following configuration creates a single file with string content (in addition to the two default directories).

mock({
  'path/to/file.txt': 'file content here'
});

To create a file with additional properties (owner, permissions, atime, etc.), use the mock.file() function described below.

mock.file(properties)

Create a factory for new files. Supported properties:

  • content - string|Buffer File contents.
  • mode - number File mode (permission and sticky bits). Defaults to 0666.
  • uid - number The user id. Defaults to process.getuid().
  • gid - number The group id. Defaults to process.getgid().
  • atime - Date The last file access time. Defaults to new Date(). Updated when file contents are accessed.
  • ctime - Date The last file change time. Defaults to new Date(). Updated when file owner or permissions change.
  • mtime - Date The last file modification time. Defaults to new Date(). Updated when file contents change.
  • birthtime - Date The time of file creation. Defaults to new Date().

To create a mock filesystem with a very old file named foo, you could do something like this:

mock({
  foo: mock.file({
    content: 'file content here',
    ctime: new Date(1),
    mtime: new Date(1)
  })
});

Note that if you want to create a file with the default properties, you can provide a string or Buffer directly instead of calling mock.file().

Creating directories

When config property values are an Object, a directory is created. The structure of the object is the same as the config object itself. So an empty directory can be created with a simple object literal ({}). The following configuration creates a directory containing two files (in addition to the two default directories):

// note that this could also be written as
// mock({'path/to/dir': { /** config */ }})
mock({
  path: {
    to: {
      dir: {
        file1: 'text content',
        file2: Buffer.from([1, 2, 3, 4])
      }
    }
  }
});

To create a directory with additional properties (owner, permissions, atime, etc.), use the mock.directory() function described below.

mock.directory(properties)

Create a factory for new directories. Supported properties:

  • mode - number Directory mode (permission and sticky bits). Defaults to 0777.
  • uid - number The user id. Defaults to process.getuid().
  • gid - number The group id. Defaults to process.getgid().
  • atime - Date The last directory access time. Defaults to new Date().
  • ctime - Date The last directory change time. Defaults to new Date(). Updated when owner or permissions change.
  • mtime - Date The last directory modification time. Defaults to new Date(). Updated when an item is added, removed, or renamed.
  • birthtime - Date The time of directory creation. Defaults to new Date().
  • items - Object Directory contents. Members will generate additional files, directories, or symlinks.

To create a mock filesystem with a directory with the relative path some/dir that has a mode of 0755 and two child files, you could do something like this:

mock({
  'some/dir': mock.directory({
    mode: 0755,
    items: {
      file1: 'file one content',
      file2: Buffer.from([8, 6, 7, 5, 3, 0, 9])
    }
  })
});

Note that if you want to create a directory with the default properties, you can provide an Object directly instead of calling mock.directory().

Using a string or a Buffer is a shortcut for creating files with default properties. Using an Object is a shortcut for creating a directory with default properties. There is no shortcut for creating symlinks. To create a symlink, you need to call the mock.symlink() function described below.

Create a factory for new symlinks. Supported properties:

  • path - string Path to the source (required).
  • mode - number Symlink mode (permission and sticky bits). Defaults to 0666.
  • uid - number The user id. Defaults to process.getuid().
  • gid - number The group id. Defaults to process.getgid().
  • atime - Date The last symlink access time. Defaults to new Date().
  • ctime - Date The last symlink change time. Defaults to new Date().
  • mtime - Date The last symlink modification time. Defaults to new Date().
  • birthtime - Date The time of symlink creation. Defaults to new Date().

To create a mock filesystem with a file and a symlink, you could do something like this:

mock({
  'some/dir': {
    'regular-file': 'file contents',
    'a-symlink': mock.symlink({
      path: 'regular-file'
    })
  }
});

Restoring the file system

mock.restore()

Restore the fs binding to the real file system. This undoes the effect of calling mock(). Typically, you would set up a mock file system before running a test and restore the original after. Using a test runner with beforeEach and afterEach hooks, this might look like the following:

beforeEach(function() {
  mock({
    'fake-file': 'file contents'
  });
});
afterEach(mock.restore);

Bypassing the mock file system

mock.bypass(fn)

Execute calls to the real filesystem with mock.bypass()

// This file exists only on the real FS, not on the mocked FS
const realFilePath = '/path/to/real/file.txt';
const myData = mock.bypass(() => fs.readFileSync(realFilePath, 'utf-8'));

If you pass an asynchronous function or a promise-returning function to bypass(), a promise will be returned.

Async Warning

Asynchronous calls are supported, however, they are not recommended as they could produce unintended consequences if anything else tries to access the mocked filesystem before they've completed.

async function getFileInfo(fileName) {
  return await mock.bypass(async () => {
    const stats = await fs.promises.stat(fileName);
    const data = await fs.promises.readFile(fileName);
    return {stats, data};
  });
}

Install

Using npm:

npm install mock-fs --save-dev

Caveats

When you require mock-fs, Node's own fs module is patched to allow the binding to the underlying file system to be swapped out. If you require mock-fs before any other modules that modify fs (e.g. graceful-fs), the mock should behave as expected.

Note mock-fs is not compatible with `graceful-fs@3.xbut works withgraceful-fs@4.x`.

Mock file access is controlled based on file mode where process.getuid() and process.getgid() are available (POSIX systems). On other systems (e.g. Windows) the file mode has no effect.

Tested on Linux, OSX, and Windows using Node 16 through 18. Check the tickets for a list of known issues.

Using with Jest Snapshot Testing

.toMatchSnapshot in Jest uses fs to load existing snapshots. If mockFs is active, Jest isn't able to load existing snapshots. In such case it accepts all snapshots without diffing the old ones, which breaks the concept of snapshot testing.

Calling mock.restore() in afterEach is too late and it's necessary to call it before snapshot matching:

const actual = testedFunction()
mock.restore()
expect(actual).toMatchSnapshot()

Note: it's safe to call mock.restore multiple times, so it can still be called in afterEach and then manually in test cases which use snapshot testing.

changelog

Change Log

5.4.1

  • Avoid errors in fs.existsSync (see #401)

5.4.0

  • Use setImmediate instead of process.nextTick (thanks @regseb, see #360)
<summary>Dependency Updates</summary>
  • bump chai from 4.3.4 to 4.5.0
  • bump eslint from 8.21.0 to 8.57.1

5.3.0

  • Remove conditions for untested versions
  • Remove disabled tests for mock.fs (thanks @everett1992, see #391)
  • Fix tests on node 20 (thanks @everett1992, see #387)
  • Fix timeout in failing test (thanks @everett1992, see #390)
  • Stop testing on Node 12 and 14
<summary>Dependency Updates</summary>
  • chore(deps-dev): bump rimraf from 3.0.2 to 6.0.1
  • chore(deps): bump actions/checkout from 2 to 4
  • chore(deps-dev): bump mocha from 9.2.2 to 10.7.3
  • chore(deps-dev): bump braces from 3.0.2 to 3.0.3
  • chore(deps-dev): bump word-wrap from 1.2.3 to 1.2.4
  • chore(deps): bump json5 from 1.0.1 to 1.0.2

5.2.0

  • Fix EACCES error on access by root user (thanks @danielkatz, see #369)
  • Fix bug on utimes and futimes; add support of lutimes (thanks @3cp, see #366)

5.1.4

  • Fix for BigInt stats in Node 16.7 (thanks @ahippler, see #363)

5.1.3

  • Fix for BigInt stats in Node 18.7 (thanks @3cp, see #361)

5.1.2

  • Avoid open FSREQCALLBACK file handles (thanks @jloleysens, see #342)

5.1.1

  • Added engines to package.json to clarify that Node >= 12 is required (thanks @tillig, see #337)

5.1.0

  • Added support for Node >= 16.3 (thanks @Rugvip, see #335)

5.0.0

Breaking change:

  • Remove support for Node < 12. If you want to use mock-fs to test on Node 10 or lower, stick with mock-fs@4.

New features:

  • Support for BigInt file stats - required for Node 15+ (thanks @3cp, see #325)

4.14.0

  • Attempt to fix logging when using mock-fs with tape (see #322)
  • Minor fix for bypass() (thanks @3cp, see #320)

4.13.0

  • Make process.chdir(), process.cwd(), and fs.createWriteStream() work with bypass() (thanks @3cp, see #307)
  • Fix memory leak associated with Node 10 (thanks @3cp, see #303)
  • Async function handling in bypass() (see #306)
  • Big new feature! Temporarily bypass the mocked filesystem with the bypass() function (thanks @nonara, see #304)

4.12.0

  • Check permissions in readdir and readdirSync (thanks @warpdesign, see #295)
  • Add support for Buffer arg on many fs functions (thanks @3cp, see #293)
  • Fix checks for read permission (thanks @3cp, see #289)
  • Correct error code for readFile on a directory (thanks @3cp, see #286)

4.11.0

  • Support withFileTypes when reading directories (thanks @mrmlnc, see #287)

4.10.4

  • Throw ENOTDIR when trying to open an incorrect path (thanks @niieani, see #282)
  • Fix maybeCallback return (thanks @3cp, see #281)

4.10.3

  • Fix bad promise rejection on some fs.promises methods (thanks @3cp, see #279)

4.10.2

  • Fix timestamps for Node > 12.10 (thanks @3cp, see #277)

4.10.1

  • Fix for fs.mkdir with the recursive option on existing directories (thanks @3cp, see #271)

4.10.0

  • Support the recursive option for fs.mkdir (thanks @3cp, see #268)

4.9.0

  • Improve readFile support for Node 10+ (thanks @huochunpeng, see #265)
  • Updated dev dependencies (see #267)

4.8.0

  • Fix compatibility issues with Node 10 and 11 (thanks @huochunpeng #260)
  • Support experimental fs.promises (thanks @huochunpeng #260)

4.7.0

  • Fix for readdir on Node 10.10 (thanks @maxwellgerber #251)
  • Fix for reading and writing using Uint8Array (thanks @maxwellgerber #249)
  • Document how to properly restore the fs with Jest snapshot testing (thanks @tricoder42 #247)
  • More informative error when opening a directory (thanks @maxwellgerber #242)

4.6.0

Note that the mocked fs.createReadStream and fs.createWriteStream are not working properly with Node 10.5+.

  • Implement binding.copyFile (#243)
  • Stat fixes for Node 10.5 (thanks @tomhughes, see [#241][#241])

4.5.0

  • Updates for Node 10 compatibility (#237)
  • Throw ENOENT in readlink when item is missing (thanks @deployable, see #232)
  • Add path to errors when it exists (thanks @deployable, see #230)

4.4.2

  • Throw if item content is invalid in config (thanks @mutantcornholio, see #221)
  • Use const in readme (thanks @denar90, see #222)

4.4.1

  • Document that tests are run on Node 8.x as well.

4.4.0

  • Fix stat issue with Node 8 (thanks @AGrzes, see #209)
  • Make code prettier (see #210)

4.3.0

  • Add support for fs.mkdtemp() and fs.mkdtempSync (see #207)

4.2.0

  • Update fs.stat(), fs.lstat(), and fs.fstat() for Node 7.7+ (thanks @not-an-aardvark, see #198)

4.1.0

  • Correctly follow a symlink chain in binding.open() (thanks @vlindhol, see #195)

4.0.0

In earlier versions of mock-fs, a monkey-patched version of the fs module was used to provide an in-memory filesystem. With each major release of Node, the mock-fs package needed to include a modified copy of the fs module. With the mock-fs@4 release, this package no longer includes a modified copy of the fs module. Instead, this package overrides process.binding('fs'). While this is not part of Node's stable API, it has proven to be a more stable interface than the fs module itself (based on experience implementing it with Node 0.8 through 7.0).

Upgrading from 3.x to 4.0 should be straightforward for most applications. There are several breaking changes that may be restored in future releases:

  • The mock.fs() function has been removed.
  • The object created by fs.stat() and friends is no longer an instance of fs.Stats (though it behaves as one).
  • Lazy require() calls do not work consistently.

Detailed changes:

  • Only override process.binding('fs') (#182)
  • Expose the root of the mocked filesystem (thanks @ciaranj, see #194)

3.12.1

  • Revert the require cache clearing behavior (#181).

3.12.0

  • Support for Node 7.x (thanks @goliney, see #174).
  • Remove calls to printDeprecation (#175).
  • Break early when checking version (thanks @isiahmeadows, see #157).
  • Add a note about restoring fs (thanks @matheuss, see #147).
  • Clear the require cache before overriding fs functions (#141)

3.11.0

  • Make require() calls use the real filesystem (#139).
  • Reduce the manual fs module patching (#140).

3.10.0

  • Fixes for Node 6.3 (#138).
  • Fix permissions issues on directories (thanks @as3richa, see #105).

3.9.0

  • Support for Node 6.x (thanks @tmcw, see #107).

3.8.0

  • Implement binding.writeBuffers() (see #94).

3.7.0

  • Add support for fs.access() and fs.accessSync() (thanks @shyiko, see #78 and #80).

3.6.0

  • Add createCwd and createTmp options to control the creation of process.cwd() and os.tmpdir() directories in the mocked filesystem (see #72).
  • Update Travis and AppVeyor configurations (see #73)
  • Remove unused dev dependency (see #75)

3.5.0

  • Support for Node 5.x (thanks @tmcw, see #69).

3.4.0

  • Support for Node 4.x (thanks @AlexMeah, see #65).

3.3.0

  • Traverse symlinks recursively (thanks @caitp, see #57).
  • Upgrade to rewire@2.3.4 (thanks @mbarlock, see #60).

3.2.0

  • Support for io.js 3.0 (thanks @JustBlackBird, see #61).

3.1.0

  • Follow symlinks in readdir() and readdirSync() (thanks @caitp, see #56).

3.0.0

  • Override process.cwd() and process.chdir() to work with mocked filesystem (thanks @timkendrick, see #41).
  • Add note about known incompatibilities (thanks @psalaets, see #45).

2.7.0

  • Support for io.js 2.0 (thanks @jwilsson, see #38).

2.6.0

  • Add birthtime to Stats objects (thanks @meandmycode, see #33).

2.5.0

  • Support for io.js 1.1 (thanks @andrewblond, see #21).
  • Testing on Windows with AppVeyor (thanks @andrewblond, see #22).

2.4.0

  • Support for Node 0.12 (thanks @mlegenhausen, see #18).

2.3.1

  • Preserve arity of callbacks (see #11).

2.3.0

  • Fixes for Node 0.11.13 (see #9).

2.2.0

  • Respect file mode on POSIX-compliant systems (see #7).
  • Add benchmarks comparing mock-fs and fs modules (see #6).

2.1.2

  • Added more complete license text.
  • Test on Node 0.9 and 0.11 in addition to 0.8 and 0.10.

2.1.1

  • Added this changelog.
  • Removed unused gruntfile.js.

2.1.0

  • Directory mtime is now updated when items are added, removed, or modified (#2).
  • Fixed several issues on Windows (see #3). One issue remains on Windows with Node 0.8 (see #4).
  • Swapped out Grunt with a single script to run tasks (see #5).

2.0.0

  • Simplified API (see #1).