File: readme.md

package info (click to toggle)
node-mock-fs 4.13.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 736 kB
  • sloc: javascript: 10,467; makefile: 24; sh: 1
file content (290 lines) | stat: -rw-r--r-- 12,518 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# `mock-fs`

The `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.

## Example

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

```js
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()`](#mockrestore). Note that calling this may be **mandatory** in some cases. See [istanbuljs/nyc#324](https://github.com/istanbuljs/nyc/issues/324#issuecomment-234018654)

```js
// 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

### <a id='mockconfigoptions'>`mock(config, options)`</a>

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`](#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.*

### <a id='options'>`options`</a>

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

#### <a id='mappingoptions'>options</a>

| 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)`

```js
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).
```js
mock({
  'path/to/file.txt': 'file content here'
});
```

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

### <a id='mockfileproperties'>`mock.file(properties)`</a>

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:
```js
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):
```js
// 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()`](mockdirectoryproperties) function described below.

### <a id='mockdirectoryproperties'>`mock.directory(properties)`</a>

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:
```js
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()`.

### Creating symlinks

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()`](#mocksymlinkproperties) function described below.

### <a id='mocksymlinkproperties'>`mock.symlink(properties)`</a>

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:
```js
mock({
  'some/dir': {
    'regular-file': 'file contents',
    'a-symlink': mock.symlink({
      path: 'regular-file'
    })
  }
});
```

### Restoring the file system

### <a id='mockrestore'>`mock.restore()`</a>

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:

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

### Bypassing the mock file system

#### <a id='mockbypass'>`mock.bypass(fn)`</a>

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

```js
// 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.

#### <a id='bypassasync'>Async Warning</a>

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.

```js
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.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](https://github.com/tschaub/mock-fs/issues).

### Using with Jest Snapshot Testing

`.toMatchSnapshot` in [Jest](https://jestjs.io/docs/en/snapshot-testing) 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:

```js
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.