···354354})
355355```
356356357357+## File System
358358+359359+Mocking the file system ensures that the tests do not depend on the actual file system, making the tests more reliable and predictable. This isolation helps in avoiding side effects from previous tests. It allows for testing error conditions and edge cases that might be difficult or impossible to replicate with an actual file system, such as permission issues, disk full scenarios, or read/write errors.
360360+361361+Vitest doesn't provide any file system mocking API out of the box. You can use `vi.mock` to mock the `fs` module manually, but it's hard to maintain. Instead, we recommend using [`memfs`](https://www.npmjs.com/package/memfs) to do that for you. `memfs` creates an in-memory file system, which simulates file system operations without touching the actual disk. This approach is fast and safe, avoiding any potential side effects on the real file system.
362362+363363+### Example
364364+365365+To automatially redirect every `fs` call to `memfs`, you can create `__mocks__/fs.cjs` and `__mocks__/fs/promises.cjs` files at the root of your project:
366366+367367+::: code-group
368368+```ts [__mocks__/fs.cjs]
369369+// we can also use `import`, but then
370370+// every export should be explicitly defined
371371+372372+const { fs } = require('memfs')
373373+module.exports = fs
374374+```
375375+376376+```ts [__mocks__/fs/promises.cjs]
377377+// we can also use `import`, but then
378378+// every export should be explicitly defined
379379+380380+const { fs } = require('memfs')
381381+module.exports = fs.promises
382382+```
383383+:::
384384+385385+```ts
386386+// hello-world.js
387387+import { readFileSync } from 'node:fs'
388388+389389+export function readHelloWorld(path) {
390390+ return readFileSync('./hello-world.txt')
391391+}
392392+```
393393+394394+```ts
395395+// hello-world.test.js
396396+import { beforeEach, expect, it, vi } from 'vitest'
397397+import { fs, vol } from 'memfs'
398398+import { readHelloWorld } from './hello-world.js'
399399+400400+// tell vitest to use fs mock from __mocks__ folder
401401+// this can be done in a setup file if fs should always be mocked
402402+vi.mock('node:fs')
403403+vi.mock('node:fs/promises')
404404+405405+beforeEach(() => {
406406+ // reset the state of in-memory fs
407407+ vol.reset()
408408+})
409409+410410+it('should return correct text', () => {
411411+ const path = './hello-world.txt'
412412+ fs.writeFileSync(path, 'hello world')
413413+414414+ const text = readHelloWorld(path)
415415+ expect(text).toBe('hello world')
416416+})
417417+418418+it('can return a value multiple times', () => {
419419+ // you can use vol.fromJSON to define several files
420420+ vol.fromJSON(
421421+ {
422422+ './dir1/hw.txt': 'hello dir1',
423423+ './dir2/hw.txt': 'hello dir2',
424424+ },
425425+ // default cwd
426426+ '/tmp'
427427+ )
428428+429429+ expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1')
430430+ expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2')
431431+})
432432+```
433433+357434## Requests
358435359436Because Vitest runs in Node, mocking network requests is tricky; web APIs are not available, so we need something that will mimic network behavior for us. We recommend [Mock Service Worker](https://mswjs.io/) to accomplish this. It will let you mock both `REST` and `GraphQL` network requests, and is framework agnostic.
+4-1
packages/web-worker/src/utils.ts
···11-import { readFileSync } from 'node:fs'
11+import { readFileSync as _readFileSync } from 'node:fs'
22import type { WorkerGlobalState } from 'vitest'
33import ponyfillStructuredClone from '@ungap/structured-clone'
44import createDebug from 'debug'
55import type { CloneOption } from './types'
66+77+// keep the reference in case it was mocked
88+const readFileSync = _readFileSync
69710export const debug = createDebug('vitest:web-worker')
811
+3-1
packages/vitest/src/runtime/execute.ts
···11import vm from 'node:vm'
22import { pathToFileURL } from 'node:url'
33-import { readFileSync } from 'node:fs'
33+import fs from 'node:fs'
44import type { ModuleCacheMap } from 'vite-node/client'
55import { DEFAULT_REQUEST_STUBS, ViteNodeRunner } from 'vite-node/client'
66import {
···1717import type { WorkerGlobalState } from '../types'
1818import { VitestMocker } from './mocker'
1919import type { ExternalModulesExecutor } from './external-executor'
2020+2121+const { readFileSync } = fs
20222123export interface ExecuteOptions extends ViteNodeRunnerOptions {
2224 mockMap: MockMap
+3-1
packages/vitest/src/runtime/external-executor.ts
···11import vm from 'node:vm'
22import { fileURLToPath, pathToFileURL } from 'node:url'
33import { dirname } from 'node:path'
44-import { existsSync, statSync } from 'node:fs'
44+import fs from 'node:fs'
55import { extname, join, normalize } from 'pathe'
66import { getCachedData, isNodeBuiltin, setCacheData } from 'vite-node/utils'
77import type { RuntimeRPC } from '../types/rpc'
···1313import { ViteExecutor } from './vm/vite-executor'
14141515const SyntheticModule: typeof VMSyntheticModule = (vm as any).SyntheticModule
1616+1717+const { existsSync, statSync } = fs
16181719// always defined when we use vm pool
1820const nativeResolve = import.meta.resolve!
+3-1
packages/vitest/src/runtime/mocker.ts
···11-import { existsSync, readdirSync } from 'node:fs'
11+import fs from 'node:fs'
22import vm from 'node:vm'
33import { basename, dirname, extname, isAbsolute, join, resolve } from 'pathe'
44import { getType, highlight } from '@vitest/utils'
···77import { getAllMockableProperties } from '../utils/base'
88import type { MockFactory, PendingSuiteMock } from '../types/mocker'
99import type { VitestExecutor } from './execute'
1010+1111+const { existsSync, readdirSync } = fs
10121113const spyModulePath = resolve(distDir, 'spy.js')
1214