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.
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
.restore(); mock
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:
mock.fs()
function has been removed. This returned
an object with fs
-like methods without overriding the
built-in fs
module.fs.Stats
is no longer an instance
of fs.Stats
(though it has all the same properties and
methods).require()
do not use the real filesystem.Some of these breaking changes may be restored in a future release.
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.You can load real files and directories into the mock system using
mock.load()
{lazy: false}
optionOption | 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'
; })
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:
string|Buffer
File
contents.number
File mode (permission
and sticky bits). Defaults to 0666
.number
The user id. Defaults to
process.getuid()
.number
The group id. Defaults to
process.getgid()
.Date
The last file access
time. Defaults to new Date()
. Updated when file contents
are accessed.Date
The last file change
time. Defaults to new Date()
. Updated when file owner or
permissions change.Date
The last file
modification time. Defaults to new Date()
. Updated when
file contents change.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()
.
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:
number
Directory mode
(permission and sticky bits). Defaults to 0777
.number
The user id. Defaults to
process.getuid()
.number
The group id. Defaults to
process.getgid()
.Date
The last directory access
time. Defaults to new Date()
.Date
The last directory change
time. Defaults to new Date()
. Updated when owner or
permissions change.Date
The last directory
modification time. Defaults to new Date()
. Updated when an
item is added, removed, or renamed.Date
The time of directory
creation. Defaults to new Date()
.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.
mock.symlink(properties)
Create a factory for new symlinks. Supported properties:
string
Path to the source
(required).number
Symlink mode (permission
and sticky bits). Defaults to 0666
.number
The user id. Defaults to
process.getuid()
.number
The group id. Defaults to
process.getgid()
.Date
The last symlink access
time. Defaults to new Date()
.Date
The last symlink change
time. Defaults to new Date()
.Date
The last symlink
modification time. Defaults to new Date()
.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'
})
}; })
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);
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.
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};
;
}) }
Using npm
:
npm install mock-fs --save-dev
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.x
but works with
graceful-fs@4.x
.
Mock fs.Stats
objects have the following properties:
dev
, ino
, nlink
,
mode
, size
, rdev
,
blksize
, blocks
, atime
,
ctime
, mtime
, birthtime
,
uid
, and gid
. In addition, all of the
is*()
method are provided (e.g. isDirectory()
,
isFile()
, et al.).
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 6 through 11. Check the tickets for a list of known issues.
.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()
.restore()
mockexpect(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.