Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
The mock-fs npm package allows you to mock the file system in Node.js, enabling you to test code that interacts with the file system without actually performing any real file system operations. This is particularly useful for unit testing and ensuring that your code behaves correctly in different file system scenarios.
Mocking a Simple File System
This feature allows you to create a simple mock file system with directories and files. The `mock` function takes an object that represents the file system structure. After setting up the mock file system, you can run your code that interacts with the file system. Finally, you call `mock.restore()` to clean up and restore the real file system.
const mock = require('mock-fs');
mock({
'path/to/fake/dir': {
'some-file.txt': 'file content here',
'empty-dir': {}
}
});
// Your code that interacts with the file system
mock.restore();
Mocking File System Errors
This feature allows you to simulate file system errors, such as permission errors. In this example, the `mock.file` function is used to create a file with no permissions. When attempting to read the file, an error is thrown, which you can catch and handle in your code.
const mock = require('mock-fs');
const fs = require('fs');
mock({
'path/to/fake/dir': {
'some-file.txt': mock.file({
content: 'file content here',
mode: 0o000 // no permissions
})
}
});
try {
fs.readFileSync('path/to/fake/dir/some-file.txt');
} catch (err) {
console.error('Error reading file:', err);
}
mock.restore();
Mocking a Large File System
This feature allows you to create a large mock file system with many files. The `mock.directory` function is used to create a directory with a large number of files. This is useful for testing how your code handles large file systems.
const mock = require('mock-fs');
mock({
'large-dir': mock.directory({
items: Array.from({ length: 1000 }, (_, i) => ({
[`file-${i}.txt`]: `content of file ${i}`
})).reduce((acc, item) => Object.assign(acc, item), {})
})
});
// Your code that interacts with the large file system
mock.restore();
The memfs package provides an in-memory file system that can be used for testing and other purposes. Unlike mock-fs, which mocks the Node.js file system module, memfs provides a complete in-memory file system implementation that can be used as a drop-in replacement for the real file system. This can be useful for more complex scenarios where you need a fully functional file system.
The fs-mock package is another library for mocking the file system in Node.js. It provides a simpler API compared to mock-fs and is designed for basic use cases. While it may not have all the features of mock-fs, it can be a good choice for simpler scenarios where you just need to mock a few files and directories.
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
mock.restore();
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 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 12 through 16. 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()
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.
5.0.0
Breaking change:
New features:
FAQs
A configurable mock file system. You know, for testing.
The npm package mock-fs receives a total of 347,621 weekly downloads. As such, mock-fs popularity was classified as popular.
We found that mock-fs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.