UNPKG

10.5 kBMarkdownView Raw
1# `mock-fs`
2
3The `mock-fs` module allows Node's built-in [`fs` module](http://nodejs.org/api/fs.html) 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.
4
5## Example
6
7The code below makes it so the `fs` module is temporarily backed by a mock file system with a few files and directories.
8
9```js
10const mock = require('mock-fs');
11
12mock({
13 'path/to/fake/dir': {
14 'some-file.txt': 'file content here',
15 'empty-dir': {/** empty directory */}
16 },
17 'path/to/some.png': Buffer.from([8, 6, 7, 5, 3, 0, 9]),
18 'some/other/path': {/** another empty directory */}
19});
20```
21
22When you are ready to restore the `fs` module (so that it is backed by your real file system), call [`mock.restore()`](#mockrestore). Note that calling this may be **mandatory** in some cases. See [istanbuljs/nyc#324](https://github.com/istanbuljs/nyc/issues/324#issuecomment-234018654)
23
24```js
25// after a test runs
26mock.restore();
27```
28
29## Upgrading to version 4
30
31Instead 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.
32
33Breaking changes:
34
35 * The `mock.fs()` function has been removed. This returned an object with `fs`-like methods without overriding the built-in `fs` module.
36 * The object created by `fs.Stats` is no longer an instance of `fs.Stats` (though it has all the same properties and methods).
37 * Lazy `require()` do not use the real filesystem.
38 * Tests are no longer run in Node < 4.
39
40Some of these breaking changes may be restored in a future release.
41
42## Docs
43
44### <a id='mockconfigoptions'>`mock(config, options)`</a>
45
46Configure the `fs` module so it is backed by an in-memory file system.
47
48Calling `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`](#options) below.
49
50Property 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.
51
52*Note that paths should always use forward slashes (`/`) - even on Windows.*
53
54### <a id='options'>`options`</a>
55
56The second (optional) argument may include the properties below.
57
58 * `createCwd` - `boolean` Create a directory for `process.cwd()`. This is `true` by default.
59 * `createTmp` - `boolean` Create a directory for `os.tmpdir()`. This is `true` by default.
60
61### Creating files
62
63When `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).
64```js
65mock({
66 'path/to/file.txt': 'file content here'
67});
68```
69
70To create a file with additional properties (owner, permissions, atime, etc.), use the [`mock.file()`](#mockfileproperties) function described below.
71
72### <a id='mockfileproperties'>`mock.file(properties)`</a>
73
74Create a factory for new files. Supported properties:
75
76 * **content** - `string|Buffer` File contents.
77 * **mode** - `number` File mode (permission and sticky bits). Defaults to `0666`.
78 * **uid** - `number` The user id. Defaults to `process.getuid()`.
79 * **gid** - `number` The group id. Defaults to `process.getgid()`.
80 * **atime** - `Date` The last file access time. Defaults to `new Date()`. Updated when file contents are accessed.
81 * **ctime** - `Date` The last file change time. Defaults to `new Date()`. Updated when file owner or permissions change.
82 * **mtime** - `Date` The last file modification time. Defaults to `new Date()`. Updated when file contents change.
83 * **birthtime** - `Date` The time of file creation. Defaults to `new Date()`.
84
85To create a mock filesystem with a very old file named `foo`, you could do something like this:
86```js
87mock({
88 foo: mock.file({
89 content: 'file content here',
90 ctime: new Date(1),
91 mtime: new Date(1)
92 })
93});
94```
95
96Note 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()`.
97
98### Creating directories
99
100When `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):
101```js
102// note that this could also be written as
103// mock({'path/to/dir': { /** config */ }})
104mock({
105 path: {
106 to: {
107 dir: {
108 file1: 'text content',
109 file2: Buffer.from([1, 2, 3, 4])
110 }
111 }
112 }
113});
114```
115
116To create a directory with additional properties (owner, permissions, atime, etc.), use the [`mock.directory()`](mockdirectoryproperties) function described below.
117
118### <a id='mockdirectoryproperties'>`mock.directory(properties)`</a>
119
120Create a factory for new directories. Supported properties:
121
122 * **mode** - `number` Directory mode (permission and sticky bits). Defaults to `0777`.
123 * **uid** - `number` The user id. Defaults to `process.getuid()`.
124 * **gid** - `number` The group id. Defaults to `process.getgid()`.
125 * **atime** - `Date` The last directory access time. Defaults to `new Date()`.
126 * **ctime** - `Date` The last directory change time. Defaults to `new Date()`. Updated when owner or permissions change.
127 * **mtime** - `Date` The last directory modification time. Defaults to `new Date()`. Updated when an item is added, removed, or renamed.
128 * **birthtime** - `Date` The time of directory creation. Defaults to `new Date()`.
129 * **items** - `Object` Directory contents. Members will generate additional files, directories, or symlinks.
130
131To 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:
132```js
133mock({
134 'some/dir': mock.directory({
135 mode: 0755,
136 items: {
137 file1: 'file one content',
138 file2: Buffer.from([8, 6, 7, 5, 3, 0, 9])
139 }
140 })
141});
142```
143
144Note that if you want to create a directory with the default properties, you can provide an `Object` directly instead of calling `mock.directory()`.
145
146### Creating symlinks
147
148Using 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()`](#mocksymlinkproperties) function described below.
149
150### <a id='mocksymlinkproperties'>`mock.symlink(properties)`</a>
151
152Create a factory for new symlinks. Supported properties:
153
154 * **path** - `string` Path to the source (required).
155 * **mode** - `number` Symlink mode (permission and sticky bits). Defaults to `0666`.
156 * **uid** - `number` The user id. Defaults to `process.getuid()`.
157 * **gid** - `number` The group id. Defaults to `process.getgid()`.
158 * **atime** - `Date` The last symlink access time. Defaults to `new Date()`.
159 * **ctime** - `Date` The last symlink change time. Defaults to `new Date()`.
160 * **mtime** - `Date` The last symlink modification time. Defaults to `new Date()`.
161 * **birthtime** - `Date` The time of symlink creation. Defaults to `new Date()`.
162
163To create a mock filesystem with a file and a symlink, you could do something like this:
164```js
165mock({
166 'some/dir': {
167 'regular-file': 'file contents',
168 'a-symlink': mock.symlink({
169 path: 'regular-file'
170 })
171 }
172});
173```
174
175### Restoring the file system
176
177### <a id='mockrestore'>`mock.restore()`</a>
178
179Restore 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:
180
181```js
182beforeEach(function() {
183 mock({
184 'fake-file': 'file contents'
185 });
186});
187afterEach(mock.restore);
188```
189
190## Install
191
192Using `npm`:
193
194```
195npm install mock-fs --save-dev
196```
197
198## Caveats
199
200When 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.
201
202**Note** `mock-fs` is not compatible with `graceful-fs@3.x` but works with `graceful-fs@4.x`.
203
204Mock `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.).
205
206Mock 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.
207
208Tested on Linux, OSX, and Windows using Node 6 through 11. Check the tickets for a list of [known issues](https://github.com/tschaub/mock-fs/issues).
209
210### Using with Jest Snapshot Testing
211
212`.toMatchSnapshot` in [Jest](https://jestjs.io/docs/en/snapshot-testing) uses `fs` to load existing snapshots.
213If `mockFs` is active, Jest isn't able to load existing snapshots. In such case it accepts all snapshots
214without diffing the old ones, which breaks the concept of snapshot testing.
215
216Calling `mock.restore()` in `afterEach` is too late and it's necessary to call it before snapshot matching:
217
218```js
219const actual = testedFunction()
220mock.restore()
221expect(actual).toMatchSnapshot()
222```
223
224Note: it's safe to call `mock.restore` multiple times, so it can still be called in `afterEach` and then manually
225in test cases which use snapshot testing.
226
227[![Current Status](https://secure.travis-ci.org/tschaub/mock-fs.png?branch=master)](https://travis-ci.org/tschaub/mock-fs)