···12121313## Mock Modules
14141515-This section describes the API that you can use when [mocking a module](/guide/mocking#modules). Beware that Vitest doesn't support mocking modules imported using `require()`.
1515+This section describes the API that you can use when [mocking a module](/guide/mocking/modules). Beware that Vitest doesn't support mocking modules imported using `require()`.
16161717### vi.mock
1818···171171Beware that if you don't call `vi.mock`, modules **are not** mocked automatically. To replicate Jest's automocking behaviour, you can call `vi.mock` for each required module inside [`setupFiles`](/config/#setupfiles).
172172:::
173173174174-If there is no `__mocks__` folder or a factory provided, Vitest will import the original module and auto-mock all its exports. For the rules applied, see [algorithm](/guide/mocking#automocking-algorithm).
174174+If there is no `__mocks__` folder or a factory provided, Vitest will import the original module and auto-mock all its exports. For the rules applied, see [algorithm](/guide/mocking/modules#automocking-algorithm).
175175176176### vi.doMock
177177···295295function importMock<T>(path: string): Promise<MaybeMockedDeep<T>>
296296```
297297298298-Imports a module with all of its properties (including nested properties) mocked. Follows the same rules that [`vi.mock`](#vi-mock) does. For the rules applied, see [algorithm](/guide/mocking#automocking-algorithm).
298298+Imports a module with all of its properties (including nested properties) mocked. Follows the same rules that [`vi.mock`](#vi-mock) does. For the rules applied, see [algorithm](/guide/mocking/modules#automocking-algorithm).
299299300300### vi.unmock
301301···420420function fn(fn?: Procedure | Constructable): Mock
421421```
422422423423-Creates a spy on a function, though can be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Also, you can manipulate its behavior with [methods](/api/mock).
424424-If no function is given, mock will return `undefined`, when invoked.
423423+Creates a spy on a function, but can also be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Additionally, you can manipulate its behavior with [methods](/api/mock).
424424+If no function is given, mock will return `undefined` when invoked.
425425426426```ts
427427const getApples = vi.fn(() => 0)
···524524After the mock was restored, you can spy on it again.
525525526526::: warning
527527-This method also does not affect mocks created during [automocking](/guide/mocking-modules#mocking-a-module).
527527+This method also does not affect mocks created during [automocking](/guide/mocking/modules#mocking-a-module).
528528529529Note that unlike [`mock.mockRestore`](/api/mock#mockrestore), `vi.restoreAllMocks` will not clear mock history or reset the mock implementation
530530:::
···768768769769## Fake Timers
770770771771-This sections describes how to work with [fake timers](/guide/mocking#timers).
771771+This sections describes how to work with [fake timers](/guide/mocking/timers).
772772773773### vi.advanceTimersByTime
774774
-7
docs/guide/cli-generated.md
···341341342342Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", "preview", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/guide/browser/config.html#browser-provider) for more information (default: `"preview"`)
343343344344-### browser.providerOptions
345345-346346-- **CLI:** `--browser.providerOptions <options>`
347347-- **Config:** [browser.providerOptions](/guide/browser/config#browser-provideroptions)
348348-349349-Options that are passed down to a browser provider. Visit [`browser.providerOptions`](https://vitest.dev/config/#browser-provideroptions) for more information
350350-351344### browser.isolate
352345353346- **CLI:** `--browser.isolate`
-410
docs/guide/mocking-modules.md
···11-# Mocking Modules
22-33-## Defining a Module
44-55-Before mocking a "module", we should define what it is. In Vitest context, the "module" is a file that exports something. Using [plugins](https://vite.dev/guide/api-plugin.html), any file can be turned into a JavaScript module. The "module object" is a namespace object that holds dynamic references to exported identifiers. Simply put, it's an object with exported methods and properties. In this example, `example.js` is a module that exports `method` and `variable`:
66-77-```js [example.js]
88-export function answer() {
99- // ...
1010- return 42
1111-}
1212-1313-export const variable = 'example'
1414-```
1515-1616-The `exampleObject` here is a module object:
1717-1818-```js [example.test.js]
1919-import * as exampleObject from './example.js'
2020-```
2121-2222-The `exampleObject` will always exist even if you imported the example using named imports:
2323-2424-```js [example.test.js]
2525-import { answer, variable } from './example.js'
2626-```
2727-2828-You can only reference `exampleObject` outside the example module itself. For example, in a test.
2929-3030-## Mocking a Module
3131-3232-For the purpose of this guide, let's introduce some definitions.
3333-3434-- **Mocked module** is a module that was completely replaced with another one.
3535-- **Spied module** is a mocked module, but its exported methods keep the original implementation. They can also be tracked.
3636-- **Mocked export** is a module export, which invocations can be tracked.
3737-- **Spied export** is a mocked export.
3838-3939-To mock a module completely, you can use the [`vi.mock` API](/api/vi#vi-mock). You can define a new module dynamically by providing a factory that returns a new module as a second argument:
4040-4141-```ts
4242-import { vi } from 'vitest'
4343-4444-// The ./example.js module will be replaced with
4545-// the result of a factory function, and the
4646-// original ./example.js module will never be called
4747-vi.mock(import('./example.js'), () => {
4848- return {
4949- answer() {
5050- // ...
5151- return 42
5252- },
5353- variable: 'mock',
5454- }
5555-})
5656-```
5757-5858-::: tip
5959-Remember that you can call `vi.mock` in a [setup file](/config/#setupfiles) to apply the module mock in every test file automatically.
6060-:::
6161-6262-::: tip
6363-Note the usage of dynamic import: `import('./example.ts')`. Vitest will strip it before the code is executed, but it allows TypeScript to properly validate the string and type the `importOriginal` method in your IDE or CLI.
6464-:::
6565-6666-If your code is trying to access a method that was not returned from this factory, Vitest will throw an error with a helpful message. Note that `answer` is not mocked, i.e. it cannot be tracked. To make it trackable, use `vi.fn()` instead:
6767-6868-```ts
6969-import { vi } from 'vitest'
7070-7171-vi.mock(import('./example.js'), () => {
7272- return {
7373- answer: vi.fn(),
7474- variable: 'mock',
7575- }
7676-})
7777-```
7878-7979-The factory method accepts an `importOriginal` function that will execute the original module and return its module object:
8080-8181-```ts
8282-import { expect, vi } from 'vitest'
8383-import { answer } from './example.js'
8484-8585-vi.mock(import('./example.js'), async (importOriginal) => {
8686- const originalModule = await importOriginal()
8787- return {
8888- answer: vi.fn(originalModule.answer),
8989- variable: 'mock',
9090- }
9191-})
9292-9393-expect(answer()).toBe(42)
9494-9595-expect(answer).toHaveBeenCalled()
9696-expect(answer).toHaveReturned(42)
9797-```
9898-9999-::: warning
100100-Note that `importOriginal` is asynchronous and needs to be awaited.
101101-:::
102102-103103-In the above example, we provided the original `answer` to the `vi.fn()` call so it can keep calling it while being tracked at the same time.
104104-105105-If you require the use of `importOriginal`, consider spying on the export directly via another API: `vi.spyOn`. Instead of replacing the whole module, you can spy only on a single exported method. To do that, you need to import the module as a namespace object:
106106-107107-```ts
108108-import { expect, vi } from 'vitest'
109109-import * as exampleObject from './example.js'
110110-111111-const spy = vi.spyOn(exampleObject, 'answer').mockReturnValue(0)
112112-113113-expect(exampleObject.answer()).toBe(0)
114114-expect(exampleObject.answer).toHaveBeenCalled()
115115-```
116116-117117-::: danger Browser Mode Support
118118-This will not work in the [Browser Mode](/guide/browser/) because it uses the browser's native ESM support to serve modules. The module namespace object is sealed and can't be reconfigured. To bypass this limitation, Vitest supports `{ spy: true }` option in `vi.mock('./example.js')`. This will automatically spy on every export in the module without replacing them with fake ones.
119119-120120-```ts
121121-import { vi } from 'vitest'
122122-import * as exampleObject from './example.js'
123123-124124-vi.mock('./example.js', { spy: true })
125125-126126-vi.mocked(exampleObject.answer).mockReturnValue(0)
127127-```
128128-:::
129129-130130-::: warning
131131-You only need to import the module as a namespace object in the file where you are using the `vi.spyOn` utility. If the `answer` is called in another file and is imported there as a named export, Vitest will be able to properly track it as long as the function that called it is called after `vi.spyOn`:
132132-133133-```ts [source.js]
134134-import { answer } from './example.js'
135135-136136-export function question() {
137137- if (answer() === 42) {
138138- return 'Ultimate Question of Life, the Universe, and Everything'
139139- }
140140-141141- return 'Unknown Question'
142142-}
143143-```
144144-:::
145145-146146-Note that `vi.spyOn` will only spy on calls that were done after it spied on the method. So, if the function is executed at the top level during an import or it was called before the spying, `vi.spyOn` will not be able to report on it.
147147-148148-To automatically mock any module before it is imported, you can call `vi.mock` with a path:
149149-150150-```ts
151151-import { vi } from 'vitest'
152152-153153-vi.mock(import('./example.js'))
154154-```
155155-156156-If the file `./__mocks__/example.js` exists, then Vitest will load it instead. Otherwise, Vitest will load the original module and replace everything recursively:
157157-158158-- All arrays will be empty
159159-- All primitives will stay untouched
160160-- All getters will return `undefined`
161161-- All methods will return `undefined`
162162-- All objects will be deeply cloned
163163-- All instances of classes and their prototypes will be cloned
164164-165165-To disable this behavior, you can pass down `spy: true` as the second argument:
166166-167167-```ts
168168-import { vi } from 'vitest'
169169-170170-vi.mock(import('./example.js'), { spy: true })
171171-```
172172-173173-Instead of returning `undefined`, all methods will call the original implementation, but you can still keep track of these calls:
174174-175175-```ts
176176-import { expect, vi } from 'vitest'
177177-import { answer } from './example.js'
178178-179179-vi.mock(import('./example.js'), { spy: true })
180180-181181-// calls the original implementation
182182-expect(answer()).toBe(42)
183183-// vitest can still track the invocations
184184-expect(answer).toHaveBeenCalled()
185185-```
186186-187187-One nice thing that mocked modules support is sharing the state between the instance and its prototype. Consider this module:
188188-189189-```ts [answer.js]
190190-export class Answer {
191191- constructor(value) {
192192- this._value = value
193193- }
194194-195195- value() {
196196- return this._value
197197- }
198198-}
199199-```
200200-201201-By mocking it, we can keep track of every invocation of `.value()` even without having access to the instance itself:
202202-203203-```ts [answer.test.js]
204204-import { expect, test, vi } from 'vitest'
205205-import { Answer } from './answer.js'
206206-207207-vi.mock(import('./answer.js'), { spy: true })
208208-209209-test('instance inherits the state', () => {
210210- // these invocations could be private inside another function
211211- // that you don't have access to in your test
212212- const answer1 = new Answer(42)
213213- const answer2 = new Answer(0)
214214-215215- expect(answer1.value()).toBe(42)
216216- expect(answer1.value).toHaveBeenCalled()
217217- // note that different instances have their own states
218218- expect(answer2.value).not.toHaveBeenCalled()
219219-220220- expect(answer2.value()).toBe(0)
221221-222222- // but the prototype state accumulates all calls
223223- expect(Answer.prototype.value).toHaveBeenCalledTimes(2)
224224- expect(Answer.prototype.value).toHaveReturned(42)
225225- expect(Answer.prototype.value).toHaveReturned(0)
226226-})
227227-```
228228-229229-This can be very useful to track calls to instances that are never exposed.
230230-231231-## Mocking Non-existing Module
232232-233233-Vitest supports mocking virtual modules. These modules don't exist on the file system, but your code imports them. For example, this can happen when your development environment is different from production. One common example is mocking `vscode` APIs in your unit tests.
234234-235235-By default, Vitest will fail transforming files if it cannot find the source of the import. To bypass this, you need to specify it in your config. You can either always redirect the import to a file, or just signal Vite to ignore it and use the `vi.mock` factory to define its exports.
236236-237237-To redirect the import, use [`test.alias`](/config/#alias) config option:
238238-239239-```ts [vitest.config.ts]
240240-import { defineConfig } from 'vitest/config'
241241-import { resolve } from 'node:path'
242242-243243-export default defineConfig({
244244- test: {
245245- alias: {
246246- vscode: resolve(import.meta.dirname, './mock/vscode.js'),
247247- },
248248- },
249249-})
250250-```
251251-252252-To mark the module as always resolved, return the same string from `resolveId` hook of a plugin:
253253-254254-```ts [vitest.config.ts]
255255-import { defineConfig } from 'vitest/config'
256256-import { resolve } from 'node:path'
257257-258258-export default defineConfig({
259259- plugins: [
260260- {
261261- name: 'virtual-vscode',
262262- resolveId(id) {
263263- if (id === 'vscode') {
264264- return 'vscode'
265265- }
266266- }
267267- }
268268- ]
269269-})
270270-```
271271-272272-Now you can use `vi.mock` as usual in your tests:
273273-274274-```ts
275275-import { vi } from 'vitest'
276276-277277-vi.mock(import('vscode'), () => {
278278- return {
279279- window: {
280280- createOutputChannel: vi.fn(),
281281- }
282282- }
283283-})
284284-```
285285-286286-## How it Works
287287-288288-Vitest implements different module mocking mechanisms depending on the environment. The only feature they share is the plugin transformer. When Vitest sees that a file has `vi.mock` inside, it will transform every static import into a dynamic one and move the `vi.mock` call to the top of the file. This allows Vitest to register the mock before the import happens without breaking the ESM rule of hoisted imports.
289289-290290-::: code-group
291291-```ts [example.js]
292292-import { answer } from './answer.js'
293293-294294-vi.mock(import('./answer.js'))
295295-296296-console.log(answer)
297297-```
298298-```ts [example.transformed.js]
299299-vi.mock('./answer.js')
300300-301301-const __vitest_module_0__ = await __handle_mock__(
302302- () => import('./answer.js')
303303-)
304304-// to keep the live binding, we have to access
305305-// the export on the module namespace
306306-console.log(__vitest_module_0__.answer())
307307-```
308308-:::
309309-310310-The `__handle_mock__` wrapper just makes sure the mock is resolved before the import is initiated, it doesn't modify the module in any way.
311311-312312-The module mocking plugins are available in the [`@vitest/mocker` package](https://github.com/vitest-dev/vitest/tree/main/packages/mocker).
313313-314314-### JSDOM, happy-dom, Node
315315-316316-When you run your tests in an emulated environment, Vitest creates a [module runner](https://vite.dev/guide/api-environment-runtimes.html#modulerunner) that can consume Vite code. The module runner is designed in such a way that Vitest can hook into the module evaluation and replace it with the mock, if it was registered. This means that Vitest runs your code in an ESM-like environment, but it doesn't use native ESM mechanism directly. This allows the test runner to bend the rules around ES Modules immutability, allowing users to call `vi.spyOn` on a seemingly ES Module.
317317-318318-### Browser Mode
319319-320320-Vitest uses native ESM in the Browser Mode. This means that we cannot replace the module so easily. Instead, Vitest intercepts the fetch request (via playwright's `page.route` or a Vite plugin API if using `preview` or `webdriverio`) and serves transformed code, if the module was mocked.
321321-322322-For example, if the module is automocked, Vitest can parse static exports and create a placeholder module:
323323-324324-::: code-group
325325-```ts [answer.js]
326326-export function answer() {
327327- return 42
328328-}
329329-```
330330-```ts [answer.transformed.js]
331331-function answer() {
332332- return 42
333333-}
334334-335335-const __private_module__ = {
336336- [Symbol.toStringTag]: 'Module',
337337- answer: vi.fn(answer),
338338-}
339339-340340-export const answer = __private_module__.answer
341341-```
342342-:::
343343-344344-The example is simplified for brevity, but the concept is unchanged. We can inject a `__private_module__` variable into the module to hold the mocked values. If the user called `vi.mock` with `spy: true`, we pass down the original value; otherwise, we create a simple `vi.fn()` mock.
345345-346346-If user defined a custom factory, this makes it harder to inject the code, but not impossible. When the mocked file is served, we first resolve the factory in the browser, then pass down the keys back to the server, and use them to create a placeholder module:
347347-348348-```ts
349349-const resolvedFactoryKeys = await resolveBrowserFactory(url)
350350-const mockedModule = `
351351-const __private_module__ = getFactoryReturnValue(${url})
352352-${resolvedFactoryKeys.map(key => `export const ${key} = __private_module__["${key}"]`).join('\n')}
353353-`
354354-```
355355-356356-This module can now be served back to the browser. You can inspect the code in the devtools when you run the tests.
357357-358358-## Mocking Modules Pitfalls
359359-360360-Beware that it is not possible to mock calls to methods that are called inside other methods of the same file. For example, in this code:
361361-362362-```ts [foobar.js]
363363-export function foo() {
364364- return 'foo'
365365-}
366366-367367-export function foobar() {
368368- return `${foo()}bar`
369369-}
370370-```
371371-372372-It is not possible to mock the `foo` method from the outside because it is referenced directly. So this code will have no effect on the `foo` call inside `foobar` (but it will affect the `foo` call in other modules):
373373-374374-```ts [foobar.test.ts]
375375-import { vi } from 'vitest'
376376-import * as mod from './foobar.js'
377377-378378-// this will only affect "foo" outside of the original module
379379-vi.spyOn(mod, 'foo')
380380-vi.mock(import('./foobar.js'), async (importOriginal) => {
381381- return {
382382- ...await importOriginal(),
383383- // this will only affect "foo" outside of the original module
384384- foo: () => 'mocked'
385385- }
386386-})
387387-```
388388-389389-You can confirm this behavior by providing the implementation to the `foobar` method directly:
390390-391391-```ts [foobar.test.js]
392392-import * as mod from './foobar.js'
393393-394394-vi.spyOn(mod, 'foo')
395395-396396-// exported foo references mocked method
397397-mod.foobar(mod.foo)
398398-```
399399-400400-```ts [foobar.js]
401401-export function foo() {
402402- return 'foo'
403403-}
404404-405405-export function foobar(injectedFoo) {
406406- return injectedFoo === foo // false
407407-}
408408-```
409409-410410-This is the intended behavior, and we do not plan to implement a workaround. Consider refactoring your code into multiple files or use techniques such as [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection). We believe that making the application testable is not the responsibility of the test runner, but of the application architecture.
+17-567
docs/guide/mocking.md
···11---
22title: Mocking | Guide
33+outline: false
34---
4556# Mocking
···12131314If you are not familiar with `vi.fn`, `vi.mock` or `vi.spyOn` methods, check the [API section](/api/vi) first.
14151515-## Dates
1616-1717-Sometimes you need to be in control of the date to ensure consistency when testing. Vitest uses [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers) package for manipulating timers, as well as system date. You can find more about the specific API in detail [here](/api/vi#vi-setsystemtime).
1818-1919-### Example
2020-2121-```js
2222-import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2323-2424-const businessHours = [9, 17]
2525-2626-function purchase() {
2727- const currentHour = new Date().getHours()
2828- const [open, close] = businessHours
2929-3030- if (currentHour > open && currentHour < close) {
3131- return { message: 'Success' }
3232- }
3333-3434- return { message: 'Error' }
3535-}
3636-3737-describe('purchasing flow', () => {
3838- beforeEach(() => {
3939- // tell vitest we use mocked time
4040- vi.useFakeTimers()
4141- })
4242-4343- afterEach(() => {
4444- // restoring date after each test run
4545- vi.useRealTimers()
4646- })
4747-4848- it('allows purchases within business hours', () => {
4949- // set hour within business hours
5050- const date = new Date(2000, 1, 1, 13)
5151- vi.setSystemTime(date)
5252-5353- // access Date.now() will result in the date set above
5454- expect(purchase()).toEqual({ message: 'Success' })
5555- })
5656-5757- it('disallows purchases outside of business hours', () => {
5858- // set hour outside business hours
5959- const date = new Date(2000, 1, 1, 19)
6060- vi.setSystemTime(date)
6161-6262- // access Date.now() will result in the date set above
6363- expect(purchase()).toEqual({ message: 'Error' })
6464- })
6565-})
6666-```
6767-6868-## Functions
6969-7070-Mocking functions can be split up into two different categories; *spying & mocking*.
7171-7272-Sometimes all you need is to validate whether or not a specific function has been called (and possibly which arguments were passed). In these cases a spy would be all we need which you can use directly with `vi.spyOn()` ([read more here](/api/vi#vi-spyon)).
7373-7474-However spies can only help you **spy** on functions, they are not able to alter the implementation of those functions. In the case where we do need to create a fake (or mocked) version of a function we can use `vi.fn()` ([read more here](/api/vi#vi-fn)).
7575-7676-We use [Tinyspy](https://github.com/tinylibs/tinyspy) as a base for mocking functions, but we have our own wrapper to make it `jest` compatible. Both `vi.fn()` and `vi.spyOn()` share the same methods, however only the return result of `vi.fn()` is callable.
7777-7878-### Example
7979-8080-```js
8181-import { afterEach, describe, expect, it, vi } from 'vitest'
8282-8383-const messages = {
8484- items: [
8585- { message: 'Simple test message', from: 'Testman' },
8686- // ...
8787- ],
8888- getLatest, // can also be a `getter or setter if supported`
8989-}
9090-9191-function getLatest(index = messages.items.length - 1) {
9292- return messages.items[index]
9393-}
9494-9595-describe('reading messages', () => {
9696- afterEach(() => {
9797- vi.restoreAllMocks()
9898- })
9999-100100- it('should get the latest message with a spy', () => {
101101- const spy = vi.spyOn(messages, 'getLatest')
102102- expect(spy.getMockName()).toEqual('getLatest')
103103-104104- expect(messages.getLatest()).toEqual(
105105- messages.items[messages.items.length - 1],
106106- )
107107-108108- expect(spy).toHaveBeenCalledTimes(1)
109109-110110- spy.mockImplementationOnce(() => 'access-restricted')
111111- expect(messages.getLatest()).toEqual('access-restricted')
112112-113113- expect(spy).toHaveBeenCalledTimes(2)
114114- })
115115-116116- it('should get with a mock', () => {
117117- const mock = vi.fn().mockImplementation(getLatest)
118118-119119- expect(mock()).toEqual(messages.items[messages.items.length - 1])
120120- expect(mock).toHaveBeenCalledTimes(1)
121121-122122- mock.mockImplementationOnce(() => 'access-restricted')
123123- expect(mock()).toEqual('access-restricted')
124124-125125- expect(mock).toHaveBeenCalledTimes(2)
126126-127127- expect(mock()).toEqual(messages.items[messages.items.length - 1])
128128- expect(mock).toHaveBeenCalledTimes(3)
129129- })
130130-})
131131-```
132132-133133-### More
134134-135135-- [Jest's Mock Functions](https://jestjs.io/docs/mock-function-api)
136136-137137-## Globals
138138-139139-You can mock global variables that are not present with `jsdom` or `node` by using [`vi.stubGlobal`](/api/vi#vi-stubglobal) helper. It will put the value of the global variable into a `globalThis` object.
140140-141141-```ts
142142-import { vi } from 'vitest'
143143-144144-const IntersectionObserverMock = vi.fn(() => ({
145145- disconnect: vi.fn(),
146146- observe: vi.fn(),
147147- takeRecords: vi.fn(),
148148- unobserve: vi.fn(),
149149-}))
150150-151151-vi.stubGlobal('IntersectionObserver', IntersectionObserverMock)
152152-153153-// now you can access it as `IntersectionObserver` or `window.IntersectionObserver`
154154-```
155155-156156-## Modules
157157-158158-See ["Mocking Modules" guide](/guide/mocking-modules).
159159-160160-## File System
161161-162162-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.
163163-164164-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.
165165-166166-### Example
167167-168168-To automatically redirect every `fs` call to `memfs`, you can create `__mocks__/fs.cjs` and `__mocks__/fs/promises.cjs` files at the root of your project:
169169-170170-::: code-group
171171-```ts [__mocks__/fs.cjs]
172172-// we can also use `import`, but then
173173-// every export should be explicitly defined
174174-175175-const { fs } = require('memfs')
176176-module.exports = fs
177177-```
178178-179179-```ts [__mocks__/fs/promises.cjs]
180180-// we can also use `import`, but then
181181-// every export should be explicitly defined
182182-183183-const { fs } = require('memfs')
184184-module.exports = fs.promises
185185-```
186186-:::
187187-188188-```ts [read-hello-world.js]
189189-import { readFileSync } from 'node:fs'
190190-191191-export function readHelloWorld(path) {
192192- return readFileSync(path, 'utf-8')
193193-}
194194-```
195195-196196-```ts [hello-world.test.js]
197197-import { beforeEach, expect, it, vi } from 'vitest'
198198-import { fs, vol } from 'memfs'
199199-import { readHelloWorld } from './read-hello-world.js'
200200-201201-// tell vitest to use fs mock from __mocks__ folder
202202-// this can be done in a setup file if fs should always be mocked
203203-vi.mock('node:fs')
204204-vi.mock('node:fs/promises')
205205-206206-beforeEach(() => {
207207- // reset the state of in-memory fs
208208- vol.reset()
209209-})
210210-211211-it('should return correct text', () => {
212212- const path = '/hello-world.txt'
213213- fs.writeFileSync(path, 'hello world')
214214-215215- const text = readHelloWorld(path)
216216- expect(text).toBe('hello world')
217217-})
218218-219219-it('can return a value multiple times', () => {
220220- // you can use vol.fromJSON to define several files
221221- vol.fromJSON(
222222- {
223223- './dir1/hw.txt': 'hello dir1',
224224- './dir2/hw.txt': 'hello dir2',
225225- },
226226- // default cwd
227227- '/tmp',
228228- )
229229-230230- expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1')
231231- expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2')
232232-})
233233-```
234234-235235-## Requests
236236-237237-Because 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 allows you to mock `http`, `WebSocket` and `GraphQL` network requests, and is framework agnostic.
238238-239239-Mock Service Worker (MSW) works by intercepting the requests your tests make, allowing you to use it without changing any of your application code. In-browser, this uses the [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). In Node.js, and for Vitest, it uses the [`@mswjs/interceptors`](https://github.com/mswjs/interceptors) library. To learn more about MSW, read their [introduction](https://mswjs.io/docs/)
240240-241241-### Configuration
242242-243243-You can use it like below in your [setup file](/config/#setupfiles)
244244-245245-::: code-group
246246-247247-```js [HTTP Setup]
248248-import { afterAll, afterEach, beforeAll } from 'vitest'
249249-import { setupServer } from 'msw/node'
250250-import { http, HttpResponse } from 'msw'
251251-252252-const posts = [
253253- {
254254- userId: 1,
255255- id: 1,
256256- title: 'first post title',
257257- body: 'first post body',
258258- },
259259- // ...
260260-]
261261-262262-export const restHandlers = [
263263- http.get('https://rest-endpoint.example/path/to/posts', () => {
264264- return HttpResponse.json(posts)
265265- }),
266266-]
267267-268268-const server = setupServer(...restHandlers)
269269-270270-// Start server before all tests
271271-beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
272272-273273-// Close server after all tests
274274-afterAll(() => server.close())
275275-276276-// Reset handlers after each test for test isolation
277277-afterEach(() => server.resetHandlers())
278278-```
279279-280280-```js [GraphQL Setup]
281281-import { afterAll, afterEach, beforeAll } from 'vitest'
282282-import { setupServer } from 'msw/node'
283283-import { graphql, HttpResponse } from 'msw'
284284-285285-const posts = [
286286- {
287287- userId: 1,
288288- id: 1,
289289- title: 'first post title',
290290- body: 'first post body',
291291- },
292292- // ...
293293-]
294294-295295-const graphqlHandlers = [
296296- graphql.query('ListPosts', () => {
297297- return HttpResponse.json({
298298- data: { posts },
299299- })
300300- }),
301301-]
302302-303303-const server = setupServer(...graphqlHandlers)
304304-305305-// Start server before all tests
306306-beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
307307-308308-// Close server after all tests
309309-afterAll(() => server.close())
310310-311311-// Reset handlers after each test for test isolation
312312-afterEach(() => server.resetHandlers())
313313-```
314314-315315-```js [WebSocket Setup]
316316-import { afterAll, afterEach, beforeAll } from 'vitest'
317317-import { setupServer } from 'msw/node'
318318-import { ws } from 'msw'
319319-320320-const chat = ws.link('wss://chat.example.com')
321321-322322-const wsHandlers = [
323323- chat.addEventListener('connection', ({ client }) => {
324324- client.addEventListener('message', (event) => {
325325- console.log('Received message from client:', event.data)
326326- // Echo the received message back to the client
327327- client.send(`Server received: ${event.data}`)
328328- })
329329- }),
330330-]
331331-332332-const server = setupServer(...wsHandlers)
333333-334334-// Start server before all tests
335335-beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
336336-337337-// Close server after all tests
338338-afterAll(() => server.close())
339339-340340-// Reset handlers after each test for test isolation
341341-afterEach(() => server.resetHandlers())
342342-```
343343-:::
344344-345345-> Configuring the server with `onUnhandledRequest: 'error'` ensures that an error is thrown whenever there is a request that does not have a corresponding request handler.
346346-347347-### More
348348-There is much more to MSW. You can access cookies and query parameters, define mock error responses, and much more! To see all you can do with MSW, read [their documentation](https://mswjs.io/docs).
349349-350350-## Timers
351351-352352-When we test code that involves timeouts or intervals, instead of having our tests wait it out or timeout, we can speed up our tests by using "fake" timers that mock calls to `setTimeout` and `setInterval`.
353353-354354-See the [`vi.useFakeTimers` API section](/api/vi#vi-usefaketimers) for a more in depth detailed API description.
355355-356356-### Example
357357-358358-```js
359359-import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
360360-361361-function executeAfterTwoHours(func) {
362362- setTimeout(func, 1000 * 60 * 60 * 2) // 2 hours
363363-}
364364-365365-function executeEveryMinute(func) {
366366- setInterval(func, 1000 * 60) // 1 minute
367367-}
368368-369369-const mock = vi.fn(() => console.log('executed'))
370370-371371-describe('delayed execution', () => {
372372- beforeEach(() => {
373373- vi.useFakeTimers()
374374- })
375375- afterEach(() => {
376376- vi.restoreAllMocks()
377377- })
378378- it('should execute the function', () => {
379379- executeAfterTwoHours(mock)
380380- vi.runAllTimers()
381381- expect(mock).toHaveBeenCalledTimes(1)
382382- })
383383- it('should not execute the function', () => {
384384- executeAfterTwoHours(mock)
385385- // advancing by 2ms won't trigger the func
386386- vi.advanceTimersByTime(2)
387387- expect(mock).not.toHaveBeenCalled()
388388- })
389389- it('should execute every minute', () => {
390390- executeEveryMinute(mock)
391391- vi.advanceTimersToNextTimer()
392392- expect(mock).toHaveBeenCalledTimes(1)
393393- vi.advanceTimersToNextTimer()
394394- expect(mock).toHaveBeenCalledTimes(2)
395395- })
396396-})
397397-```
398398-399399-## Classes
400400-401401-You can mock an entire class with a single `vi.fn` call.
402402-403403-```ts
404404-class Dog {
405405- name: string
406406-407407- constructor(name: string) {
408408- this.name = name
409409- }
410410-411411- static getType(): string {
412412- return 'animal'
413413- }
414414-415415- greet = (): string => {
416416- return `Hi! My name is ${this.name}!`
417417- }
418418-419419- speak(): string {
420420- return 'bark!'
421421- }
422422-423423- isHungry() {}
424424- feed() {}
425425-}
426426-```
427427-428428-We can re-create this class with `vi.fn` (or `vi.spyOn().mockImplementation()`):
429429-430430-```ts
431431-const Dog = vi.fn(class {
432432- static getType = vi.fn(() => 'mocked animal')
433433-434434- constructor(name) {
435435- this.name = name
436436- }
437437-438438- greet = vi.fn(() => `Hi! My name is ${this.name}!`)
439439- speak = vi.fn(() => 'loud bark!')
440440- feed = vi.fn()
441441-})
442442-```
443443-444444-::: warning
445445-If a non-primitive is returned from the constructor function, that value will become the result of the new expression. In this case the `[[Prototype]]` may not be correctly bound:
446446-447447-```ts
448448-const CorrectDogClass = vi.fn(function (name) {
449449- this.name = name
450450-})
451451-452452-const IncorrectDogClass = vi.fn(name => ({
453453- name
454454-}))
455455-456456-const Marti = new CorrectDogClass('Marti')
457457-const Newt = new IncorrectDogClass('Newt')
458458-459459-Marti instanceof CorrectDogClass // ✅ true
460460-Newt instanceof IncorrectDogClass // ❌ false!
461461-```
462462-463463-If you are mocking classes, prefer the class syntax over the function.
464464-:::
465465-466466-::: tip WHEN TO USE?
467467-Generally speaking, you would re-create a class like this inside the module factory if the class is re-exported from another module:
468468-469469-```ts
470470-import { Dog } from './dog.js'
471471-472472-vi.mock(import('./dog.js'), () => {
473473- const Dog = vi.fn(class {
474474- feed = vi.fn()
475475- // ... other mocks
476476- })
477477- return { Dog }
478478-})
479479-```
480480-481481-This method can also be used to pass an instance of a class to a function that accepts the same interface:
482482-483483-```ts [src/feed.ts]
484484-function feed(dog: Dog) {
485485- // ...
486486-}
487487-```
488488-```ts [tests/dog.test.ts]
489489-import { expect, test, vi } from 'vitest'
490490-import { feed } from '../src/feed.js'
491491-492492-const Dog = vi.fn(class {
493493- feed = vi.fn()
494494-})
495495-496496-test('can feed dogs', () => {
497497- const dogMax = new Dog('Max')
498498-499499- feed(dogMax)
500500-501501- expect(dogMax.feed).toHaveBeenCalled()
502502- expect(dogMax.isHungry()).toBe(false)
503503-})
504504-```
505505-:::
506506-507507-Now, when we create a new instance of the `Dog` class its `speak` method (alongside `feed` and `greet`) is already mocked:
508508-509509-```ts
510510-const Cooper = new Dog('Cooper')
511511-Cooper.speak() // loud bark!
512512-Cooper.greet() // Hi! My name is Cooper!
513513-514514-// you can use built-in assertions to check the validity of the call
515515-expect(Cooper.speak).toHaveBeenCalled()
516516-expect(Cooper.greet).toHaveBeenCalled()
517517-518518-const Max = new Dog('Max')
519519-520520-// methods are not shared between instances if you assigned them directly
521521-expect(Max.speak).not.toHaveBeenCalled()
522522-expect(Max.greet).not.toHaveBeenCalled()
523523-```
524524-525525-We can reassign the return value for a specific instance:
526526-527527-```ts
528528-const dog = new Dog('Cooper')
529529-530530-// "vi.mocked" is a type helper, since
531531-// TypeScript doesn't know that Dog is a mocked class,
532532-// it wraps any function in a Mock<T> type
533533-// without validating if the function is a mock
534534-vi.mocked(dog.speak).mockReturnValue('woof woof')
535535-536536-dog.speak() // woof woof
537537-```
538538-539539-To mock the property, we can use the `vi.spyOn(dog, 'name', 'get')` method. This makes it possible to use spy assertions on the mocked property:
540540-541541-```ts
542542-const dog = new Dog('Cooper')
543543-544544-const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max')
545545-546546-expect(dog.name).toBe('Max')
547547-expect(nameSpy).toHaveBeenCalledTimes(1)
548548-```
549549-550550-::: tip
551551-You can also spy on getters and setters using the same method.
552552-:::
553553-554554-::: danger
555555-Using classes with `vi.fn()` was introduced in Vitest 4. Previously, you had to use `function` and `prototype` inheritence directly. See [v3 guide](https://v3.vitest.dev/guide/mocking.html#classes).
556556-:::
1616+Vitest has a comprehensive list of guides regarding mocking:
1717+1818+- [Mocking Classes](/guide/mocking/classes.md)
1919+- [Mocking Dates](/guide/mocking/dates.md)
2020+- [Mocking the File System](/guide/mocking/file-system.md)
2121+- [Mocking Functions](/guide/mocking/functions.md)
2222+- [Mocking Globals](/guide/mocking/globals.md)
2323+- [Mocking Modules](/guide/mocking/modules.md)
2424+- [Mocking Requests](/guide/mocking/requests.md)
2525+- [Mocking Timers](/guide/mocking/timers.md)
2626+2727+For a simpler and quicker way to get started with mocking, you can check the Cheat Sheet below.
5572855829## Cheat Sheet
559559-560560-:::info
561561-`vi` in the examples below is imported directly from `vitest`. You can also use it globally, if you set `globals` to `true` in your [config](/config/).
562562-:::
5633056431I want to…
56532···62289 })
62390 return { SomeClass }
62491})
625625-// SomeClass.mock.instances will have SomeClass
62692```
62793628628-2. Example with `vi.mock` and `.prototype`:
629629-```ts [example.js]
630630-export class SomeClass {}
631631-```
632632-```ts
633633-import { SomeClass } from './example.js'
634634-635635-vi.mock(import('./example.js'), () => {
636636- const SomeClass = vi.fn()
637637- SomeClass.prototype.someMethod = vi.fn()
638638- return { SomeClass }
639639-})
640640-// SomeClass.mock.instances will have SomeClass
641641-```
642642-643643-3. Example with `vi.spyOn`:
9494+2. Example with `vi.spyOn`:
6449564596```ts
64697import * as mod from './example.js'
64798648648-const SomeClass = vi.fn()
649649-SomeClass.prototype.someMethod = vi.fn()
650650-651651-vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass)
9999+vi.spyOn(mod, 'SomeClass').mockImplementation(class FakeClass {
100100+ someMethod = vi.fn()
101101+})
652102```
653103654104::: warning
···11+# Mocking Classes
22+33+You can mock an entire class with a single [`vi.fn`](/api/vi#fn) call.
44+55+```ts
66+class Dog {
77+ name: string
88+99+ constructor(name: string) {
1010+ this.name = name
1111+ }
1212+1313+ static getType(): string {
1414+ return 'animal'
1515+ }
1616+1717+ greet = (): string => {
1818+ return `Hi! My name is ${this.name}!`
1919+ }
2020+2121+ speak(): string {
2222+ return 'bark!'
2323+ }
2424+2525+ isHungry() {}
2626+ feed() {}
2727+}
2828+```
2929+3030+We can re-create this class with `vi.fn` (or `vi.spyOn().mockImplementation()`):
3131+3232+```ts
3333+const Dog = vi.fn(class {
3434+ static getType = vi.fn(() => 'mocked animal')
3535+3636+ constructor(name) {
3737+ this.name = name
3838+ }
3939+4040+ greet = vi.fn(() => `Hi! My name is ${this.name}!`)
4141+ speak = vi.fn(() => 'loud bark!')
4242+ feed = vi.fn()
4343+})
4444+```
4545+4646+::: warning
4747+If a non-primitive is returned from the constructor function, that value will become the result of the new expression. In this case the `[[Prototype]]` may not be correctly bound:
4848+4949+```ts
5050+const CorrectDogClass = vi.fn(function (name) {
5151+ this.name = name
5252+})
5353+5454+const IncorrectDogClass = vi.fn(name => ({
5555+ name
5656+}))
5757+5858+const Marti = new CorrectDogClass('Marti')
5959+const Newt = new IncorrectDogClass('Newt')
6060+6161+Marti instanceof CorrectDogClass // ✅ true
6262+Newt instanceof IncorrectDogClass // ❌ false!
6363+```
6464+6565+If you are mocking classes, prefer the class syntax over the function.
6666+:::
6767+6868+::: tip WHEN TO USE?
6969+Generally speaking, you would re-create a class like this inside the module factory if the class is re-exported from another module:
7070+7171+```ts
7272+import { Dog } from './dog.js'
7373+7474+vi.mock(import('./dog.js'), () => {
7575+ const Dog = vi.fn(class {
7676+ feed = vi.fn()
7777+ // ... other mocks
7878+ })
7979+ return { Dog }
8080+})
8181+```
8282+8383+This method can also be used to pass an instance of a class to a function that accepts the same interface:
8484+8585+```ts [src/feed.ts]
8686+function feed(dog: Dog) {
8787+ // ...
8888+}
8989+```
9090+```ts [tests/dog.test.ts]
9191+import { expect, test, vi } from 'vitest'
9292+import { feed } from '../src/feed.js'
9393+9494+const Dog = vi.fn(class {
9595+ feed = vi.fn()
9696+})
9797+9898+test('can feed dogs', () => {
9999+ const dogMax = new Dog('Max')
100100+101101+ feed(dogMax)
102102+103103+ expect(dogMax.feed).toHaveBeenCalled()
104104+ expect(dogMax.isHungry()).toBe(false)
105105+})
106106+```
107107+:::
108108+109109+Now, when we create a new instance of the `Dog` class its `speak` method (alongside `feed` and `greet`) is already mocked:
110110+111111+```ts
112112+const Cooper = new Dog('Cooper')
113113+Cooper.speak() // loud bark!
114114+Cooper.greet() // Hi! My name is Cooper!
115115+116116+// you can use built-in assertions to check the validity of the call
117117+expect(Cooper.speak).toHaveBeenCalled()
118118+expect(Cooper.greet).toHaveBeenCalled()
119119+120120+const Max = new Dog('Max')
121121+122122+// methods are not shared between instances if you assigned them directly
123123+expect(Max.speak).not.toHaveBeenCalled()
124124+expect(Max.greet).not.toHaveBeenCalled()
125125+```
126126+127127+We can reassign the return value for a specific instance:
128128+129129+```ts
130130+const dog = new Dog('Cooper')
131131+132132+// "vi.mocked" is a type helper, since
133133+// TypeScript doesn't know that Dog is a mocked class,
134134+// it wraps any function in a Mock<T> type
135135+// without validating if the function is a mock
136136+vi.mocked(dog.speak).mockReturnValue('woof woof')
137137+138138+dog.speak() // woof woof
139139+```
140140+141141+To mock the property, we can use the `vi.spyOn(dog, 'name', 'get')` method. This makes it possible to use spy assertions on the mocked property:
142142+143143+```ts
144144+const dog = new Dog('Cooper')
145145+146146+const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max')
147147+148148+expect(dog.name).toBe('Max')
149149+expect(nameSpy).toHaveBeenCalledTimes(1)
150150+```
151151+152152+::: tip
153153+You can also spy on getters and setters using the same method.
154154+:::
155155+156156+::: danger
157157+Using classes with `vi.fn()` was introduced in Vitest 4. Previously, you had to use `function` and `prototype` inheritence directly. See [v3 guide](https://v3.vitest.dev/guide/mocking.html#classes).
158158+:::
+52
docs/guide/mocking/dates.md
···11+# Mocking Dates
22+33+Sometimes you need to be in control of the date to ensure consistency when testing. Vitest uses [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers) package for manipulating timers, as well as system date. You can find more about the specific API in detail [here](/api/vi#vi-setsystemtime).
44+55+## Example
66+77+```js
88+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
99+1010+const businessHours = [9, 17]
1111+1212+function purchase() {
1313+ const currentHour = new Date().getHours()
1414+ const [open, close] = businessHours
1515+1616+ if (currentHour > open && currentHour < close) {
1717+ return { message: 'Success' }
1818+ }
1919+2020+ return { message: 'Error' }
2121+}
2222+2323+describe('purchasing flow', () => {
2424+ beforeEach(() => {
2525+ // tell vitest we use mocked time
2626+ vi.useFakeTimers()
2727+ })
2828+2929+ afterEach(() => {
3030+ // restoring date after each test run
3131+ vi.useRealTimers()
3232+ })
3333+3434+ it('allows purchases within business hours', () => {
3535+ // set hour within business hours
3636+ const date = new Date(2000, 1, 1, 13)
3737+ vi.setSystemTime(date)
3838+3939+ // access Date.now() will result in the date set above
4040+ expect(purchase()).toEqual({ message: 'Success' })
4141+ })
4242+4343+ it('disallows purchases outside of business hours', () => {
4444+ // set hour outside business hours
4545+ const date = new Date(2000, 1, 1, 19)
4646+ vi.setSystemTime(date)
4747+4848+ // access Date.now() will result in the date set above
4949+ expect(purchase()).toEqual({ message: 'Error' })
5050+ })
5151+})
5252+```
+74
docs/guide/mocking/file-system.md
···11+# Mocking the File System
22+33+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.
44+55+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.
66+77+## Example
88+99+To automatically redirect every `fs` call to `memfs`, you can create `__mocks__/fs.cjs` and `__mocks__/fs/promises.cjs` files at the root of your project:
1010+1111+::: code-group
1212+```ts [__mocks__/fs.cjs]
1313+// we can also use `import`, but then
1414+// every export should be explicitly defined
1515+1616+const { fs } = require('memfs')
1717+module.exports = fs
1818+```
1919+2020+```ts [__mocks__/fs/promises.cjs]
2121+// we can also use `import`, but then
2222+// every export should be explicitly defined
2323+2424+const { fs } = require('memfs')
2525+module.exports = fs.promises
2626+```
2727+:::
2828+2929+```ts [read-hello-world.js]
3030+import { readFileSync } from 'node:fs'
3131+3232+export function readHelloWorld(path) {
3333+ return readFileSync(path, 'utf-8')
3434+}
3535+```
3636+3737+```ts [hello-world.test.js]
3838+import { beforeEach, expect, it, vi } from 'vitest'
3939+import { fs, vol } from 'memfs'
4040+import { readHelloWorld } from './read-hello-world.js'
4141+4242+// tell vitest to use fs mock from __mocks__ folder
4343+// this can be done in a setup file if fs should always be mocked
4444+vi.mock('node:fs')
4545+vi.mock('node:fs/promises')
4646+4747+beforeEach(() => {
4848+ // reset the state of in-memory fs
4949+ vol.reset()
5050+})
5151+5252+it('should return correct text', () => {
5353+ const path = '/hello-world.txt'
5454+ fs.writeFileSync(path, 'hello world')
5555+5656+ const text = readHelloWorld(path)
5757+ expect(text).toBe('hello world')
5858+})
5959+6060+it('can return a value multiple times', () => {
6161+ // you can use vol.fromJSON to define several files
6262+ vol.fromJSON(
6363+ {
6464+ './dir1/hw.txt': 'hello dir1',
6565+ './dir2/hw.txt': 'hello dir2',
6666+ },
6767+ // default cwd
6868+ '/tmp',
6969+ )
7070+7171+ expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1')
7272+ expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2')
7373+})
7474+```
+61
docs/guide/mocking/functions.md
···11+# Mocking Functions
22+33+Mocking functions can be split up into two different categories: spying and mocking.
44+55+If you need to observe the behaviour of a method on an object, you can use [`vi.spyOn()`](/api/vi#vi-spyon) to create a spy that tracks calls to that method.
66+77+If you need to pass down a custom function implementation as an argument or create a new mocked entity, you can use [`vi.fn()`](/api/vi#vi-fn) to create a mock function.
88+99+Both `vi.spyOn` and `vi.fn` share the same methods.
1010+1111+## Example
1212+1313+```js
1414+import { afterEach, describe, expect, it, vi } from 'vitest'
1515+1616+const messages = {
1717+ items: [
1818+ { message: 'Simple test message', from: 'Testman' },
1919+ // ...
2020+ ],
2121+ addItem(item) {
2222+ messages.items.push(item)
2323+ messages.callbacks.forEach(callback => callback(item))
2424+ },
2525+ onItem(callback) {
2626+ messages.callbacks.push(callback)
2727+ },
2828+ getLatest, // can also be a `getter or setter if supported`
2929+}
3030+3131+function getLatest(index = messages.items.length - 1) {
3232+ return messages.items[index]
3333+}
3434+3535+it('should get the latest message with a spy', () => {
3636+ const spy = vi.spyOn(messages, 'getLatest')
3737+ expect(spy.getMockName()).toEqual('getLatest')
3838+3939+ expect(messages.getLatest()).toEqual(
4040+ messages.items[messages.items.length - 1],
4141+ )
4242+4343+ expect(spy).toHaveBeenCalledTimes(1)
4444+4545+ spy.mockImplementationOnce(() => 'access-restricted')
4646+ expect(messages.getLatest()).toEqual('access-restricted')
4747+4848+ expect(spy).toHaveBeenCalledTimes(2)
4949+})
5050+5151+it('passing down the mock', () => {
5252+ const callback = vi.fn()
5353+ messages.onItem(callback)
5454+5555+ messages.addItem({ message: 'Another test message', from: 'Testman' })
5656+ expect(callback).toHaveBeenCalledWith({
5757+ message: 'Another test message',
5858+ from: 'Testman',
5959+ })
6060+})
6161+```
+20
docs/guide/mocking/globals.md
···11+# Mocking Globals
22+33+You can mock global variables that are not present with `jsdom` or `node` by using [`vi.stubGlobal`](/api/vi#vi-stubglobal) helper. It will put the value of the global variable into a `globalThis` object.
44+55+By default, Vitest does not reset these globals, but you can turn on the [`unstubGlobals`](/config/#unstubglobals) option in your config to restore the original values after each test or call [`vi.unstubAllGlobals()`](/api/vi#vi-unstuballglobals) manually.
66+77+```ts
88+import { vi } from 'vitest'
99+1010+const IntersectionObserverMock = vi.fn(() => ({
1111+ disconnect: vi.fn(),
1212+ observe: vi.fn(),
1313+ takeRecords: vi.fn(),
1414+ unobserve: vi.fn(),
1515+}))
1616+1717+vi.stubGlobal('IntersectionObserver', IntersectionObserverMock)
1818+1919+// now you can access it as `IntersectionObserver` or `window.IntersectionObserver`
2020+```
+412
docs/guide/mocking/modules.md
···11+# Mocking Modules
22+33+## Defining a Module
44+55+Before mocking a "module", we should define what it is. In Vitest context, the "module" is a file that exports something. Using [plugins](https://vite.dev/guide/api-plugin.html), any file can be turned into a JavaScript module. The "module object" is a namespace object that holds dynamic references to exported identifiers. Simply put, it's an object with exported methods and properties. In this example, `example.js` is a module that exports `method` and `variable`:
66+77+```js [example.js]
88+export function answer() {
99+ // ...
1010+ return 42
1111+}
1212+1313+export const variable = 'example'
1414+```
1515+1616+The `exampleObject` here is a module object:
1717+1818+```js [example.test.js]
1919+import * as exampleObject from './example.js'
2020+```
2121+2222+The `exampleObject` will always exist even if you imported the example using named imports:
2323+2424+```js [example.test.js]
2525+import { answer, variable } from './example.js'
2626+```
2727+2828+You can only reference `exampleObject` outside the example module itself. For example, in a test.
2929+3030+## Mocking a Module
3131+3232+For the purpose of this guide, let's introduce some definitions.
3333+3434+- **Mocked module** is a module that was completely replaced with another one.
3535+- **Spied module** is a mocked module, but its exported methods keep the original implementation. They can also be tracked.
3636+- **Mocked export** is a module export, which invocations can be tracked.
3737+- **Spied export** is a mocked export.
3838+3939+To mock a module completely, you can use the [`vi.mock` API](/api/vi#vi-mock). You can define a new module dynamically by providing a factory that returns a new module as a second argument:
4040+4141+```ts
4242+import { vi } from 'vitest'
4343+4444+// The ./example.js module will be replaced with
4545+// the result of a factory function, and the
4646+// original ./example.js module will never be called
4747+vi.mock(import('./example.js'), () => {
4848+ return {
4949+ answer() {
5050+ // ...
5151+ return 42
5252+ },
5353+ variable: 'mock',
5454+ }
5555+})
5656+```
5757+5858+::: tip
5959+Remember that you can call `vi.mock` in a [setup file](/config/#setupfiles) to apply the module mock in every test file automatically.
6060+:::
6161+6262+::: tip
6363+Note the usage of dynamic import: `import('./example.ts')`. Vitest will strip it before the code is executed, but it allows TypeScript to properly validate the string and type the `importOriginal` method in your IDE or CLI.
6464+:::
6565+6666+If your code is trying to access a method that was not returned from this factory, Vitest will throw an error with a helpful message. Note that `answer` is not mocked, i.e. it cannot be tracked. To make it trackable, use `vi.fn()` instead:
6767+6868+```ts
6969+import { vi } from 'vitest'
7070+7171+vi.mock(import('./example.js'), () => {
7272+ return {
7373+ answer: vi.fn(),
7474+ variable: 'mock',
7575+ }
7676+})
7777+```
7878+7979+The factory method accepts an `importOriginal` function that will execute the original module and return its module object:
8080+8181+```ts
8282+import { expect, vi } from 'vitest'
8383+import { answer } from './example.js'
8484+8585+vi.mock(import('./example.js'), async (importOriginal) => {
8686+ const originalModule = await importOriginal()
8787+ return {
8888+ answer: vi.fn(originalModule.answer),
8989+ variable: 'mock',
9090+ }
9191+})
9292+9393+expect(answer()).toBe(42)
9494+9595+expect(answer).toHaveBeenCalled()
9696+expect(answer).toHaveReturned(42)
9797+```
9898+9999+::: warning
100100+Note that `importOriginal` is asynchronous and needs to be awaited.
101101+:::
102102+103103+In the above example, we provided the original `answer` to the `vi.fn()` call so it can keep calling it while being tracked at the same time.
104104+105105+If you require the use of `importOriginal`, consider spying on the export directly via another API: `vi.spyOn`. Instead of replacing the whole module, you can spy only on a single exported method. To do that, you need to import the module as a namespace object:
106106+107107+```ts
108108+import { expect, vi } from 'vitest'
109109+import * as exampleObject from './example.js'
110110+111111+const spy = vi.spyOn(exampleObject, 'answer').mockReturnValue(0)
112112+113113+expect(exampleObject.answer()).toBe(0)
114114+expect(exampleObject.answer).toHaveBeenCalled()
115115+```
116116+117117+::: danger Browser Mode Support
118118+This will not work in the [Browser Mode](/guide/browser/) because it uses the browser's native ESM support to serve modules. The module namespace object is sealed and can't be reconfigured. To bypass this limitation, Vitest supports `{ spy: true }` option in `vi.mock('./example.js')`. This will automatically spy on every export in the module without replacing them with fake ones.
119119+120120+```ts
121121+import { vi } from 'vitest'
122122+import * as exampleObject from './example.js'
123123+124124+vi.mock('./example.js', { spy: true })
125125+126126+vi.mocked(exampleObject.answer).mockReturnValue(0)
127127+```
128128+:::
129129+130130+::: warning
131131+You only need to import the module as a namespace object in the file where you are using the `vi.spyOn` utility. If the `answer` is called in another file and is imported there as a named export, Vitest will be able to properly track it as long as the function that called it is called after `vi.spyOn`:
132132+133133+```ts [source.js]
134134+import { answer } from './example.js'
135135+136136+export function question() {
137137+ if (answer() === 42) {
138138+ return 'Ultimate Question of Life, the Universe, and Everything'
139139+ }
140140+141141+ return 'Unknown Question'
142142+}
143143+```
144144+:::
145145+146146+Note that `vi.spyOn` will only spy on calls that were done after it spied on the method. So, if the function is executed at the top level during an import or it was called before the spying, `vi.spyOn` will not be able to report on it.
147147+148148+To automatically mock any module before it is imported, you can call `vi.mock` with a path:
149149+150150+```ts
151151+import { vi } from 'vitest'
152152+153153+vi.mock(import('./example.js'))
154154+```
155155+156156+If the file `./__mocks__/example.js` exists, then Vitest will load it instead. Otherwise, Vitest will load the original module and replace everything recursively:
157157+158158+{#automocking-algorithm}
159159+160160+- All arrays will be empty
161161+- All primitives will stay untouched
162162+- All getters will return `undefined`
163163+- All methods will return `undefined`
164164+- All objects will be deeply cloned
165165+- All instances of classes and their prototypes will be cloned
166166+167167+To disable this behavior, you can pass down `spy: true` as the second argument:
168168+169169+```ts
170170+import { vi } from 'vitest'
171171+172172+vi.mock(import('./example.js'), { spy: true })
173173+```
174174+175175+Instead of returning `undefined`, all methods will call the original implementation, but you can still keep track of these calls:
176176+177177+```ts
178178+import { expect, vi } from 'vitest'
179179+import { answer } from './example.js'
180180+181181+vi.mock(import('./example.js'), { spy: true })
182182+183183+// calls the original implementation
184184+expect(answer()).toBe(42)
185185+// vitest can still track the invocations
186186+expect(answer).toHaveBeenCalled()
187187+```
188188+189189+One nice thing that mocked modules support is sharing the state between the instance and its prototype. Consider this module:
190190+191191+```ts [answer.js]
192192+export class Answer {
193193+ constructor(value) {
194194+ this._value = value
195195+ }
196196+197197+ value() {
198198+ return this._value
199199+ }
200200+}
201201+```
202202+203203+By mocking it, we can keep track of every invocation of `.value()` even without having access to the instance itself:
204204+205205+```ts [answer.test.js]
206206+import { expect, test, vi } from 'vitest'
207207+import { Answer } from './answer.js'
208208+209209+vi.mock(import('./answer.js'), { spy: true })
210210+211211+test('instance inherits the state', () => {
212212+ // these invocations could be private inside another function
213213+ // that you don't have access to in your test
214214+ const answer1 = new Answer(42)
215215+ const answer2 = new Answer(0)
216216+217217+ expect(answer1.value()).toBe(42)
218218+ expect(answer1.value).toHaveBeenCalled()
219219+ // note that different instances have their own states
220220+ expect(answer2.value).not.toHaveBeenCalled()
221221+222222+ expect(answer2.value()).toBe(0)
223223+224224+ // but the prototype state accumulates all calls
225225+ expect(Answer.prototype.value).toHaveBeenCalledTimes(2)
226226+ expect(Answer.prototype.value).toHaveReturned(42)
227227+ expect(Answer.prototype.value).toHaveReturned(0)
228228+})
229229+```
230230+231231+This can be very useful to track calls to instances that are never exposed.
232232+233233+## Mocking Non-existing Module
234234+235235+Vitest supports mocking virtual modules. These modules don't exist on the file system, but your code imports them. For example, this can happen when your development environment is different from production. One common example is mocking `vscode` APIs in your unit tests.
236236+237237+By default, Vitest will fail transforming files if it cannot find the source of the import. To bypass this, you need to specify it in your config. You can either always redirect the import to a file, or just signal Vite to ignore it and use the `vi.mock` factory to define its exports.
238238+239239+To redirect the import, use [`test.alias`](/config/#alias) config option:
240240+241241+```ts [vitest.config.ts]
242242+import { defineConfig } from 'vitest/config'
243243+import { resolve } from 'node:path'
244244+245245+export default defineConfig({
246246+ test: {
247247+ alias: {
248248+ vscode: resolve(import.meta.dirname, './mock/vscode.js'),
249249+ },
250250+ },
251251+})
252252+```
253253+254254+To mark the module as always resolved, return the same string from `resolveId` hook of a plugin:
255255+256256+```ts [vitest.config.ts]
257257+import { defineConfig } from 'vitest/config'
258258+import { resolve } from 'node:path'
259259+260260+export default defineConfig({
261261+ plugins: [
262262+ {
263263+ name: 'virtual-vscode',
264264+ resolveId(id) {
265265+ if (id === 'vscode') {
266266+ return 'vscode'
267267+ }
268268+ }
269269+ }
270270+ ]
271271+})
272272+```
273273+274274+Now you can use `vi.mock` as usual in your tests:
275275+276276+```ts
277277+import { vi } from 'vitest'
278278+279279+vi.mock(import('vscode'), () => {
280280+ return {
281281+ window: {
282282+ createOutputChannel: vi.fn(),
283283+ }
284284+ }
285285+})
286286+```
287287+288288+## How it Works
289289+290290+Vitest implements different module mocking mechanisms depending on the environment. The only feature they share is the plugin transformer. When Vitest sees that a file has `vi.mock` inside, it will transform every static import into a dynamic one and move the `vi.mock` call to the top of the file. This allows Vitest to register the mock before the import happens without breaking the ESM rule of hoisted imports.
291291+292292+::: code-group
293293+```ts [example.js]
294294+import { answer } from './answer.js'
295295+296296+vi.mock(import('./answer.js'))
297297+298298+console.log(answer)
299299+```
300300+```ts [example.transformed.js]
301301+vi.mock('./answer.js')
302302+303303+const __vitest_module_0__ = await __handle_mock__(
304304+ () => import('./answer.js')
305305+)
306306+// to keep the live binding, we have to access
307307+// the export on the module namespace
308308+console.log(__vitest_module_0__.answer())
309309+```
310310+:::
311311+312312+The `__handle_mock__` wrapper just makes sure the mock is resolved before the import is initiated, it doesn't modify the module in any way.
313313+314314+The module mocking plugins are available in the [`@vitest/mocker` package](https://github.com/vitest-dev/vitest/tree/main/packages/mocker).
315315+316316+### JSDOM, happy-dom, Node
317317+318318+When you run your tests in an emulated environment, Vitest creates a [module runner](https://vite.dev/guide/api-environment-runtimes.html#modulerunner) that can consume Vite code. The module runner is designed in such a way that Vitest can hook into the module evaluation and replace it with the mock, if it was registered. This means that Vitest runs your code in an ESM-like environment, but it doesn't use native ESM mechanism directly. This allows the test runner to bend the rules around ES Modules immutability, allowing users to call `vi.spyOn` on a seemingly ES Module.
319319+320320+### Browser Mode
321321+322322+Vitest uses native ESM in the Browser Mode. This means that we cannot replace the module so easily. Instead, Vitest intercepts the fetch request (via playwright's `page.route` or a Vite plugin API if using `preview` or `webdriverio`) and serves transformed code, if the module was mocked.
323323+324324+For example, if the module is automocked, Vitest can parse static exports and create a placeholder module:
325325+326326+::: code-group
327327+```ts [answer.js]
328328+export function answer() {
329329+ return 42
330330+}
331331+```
332332+```ts [answer.transformed.js]
333333+function answer() {
334334+ return 42
335335+}
336336+337337+const __private_module__ = {
338338+ [Symbol.toStringTag]: 'Module',
339339+ answer: vi.fn(answer),
340340+}
341341+342342+export const answer = __private_module__.answer
343343+```
344344+:::
345345+346346+The example is simplified for brevity, but the concept is unchanged. We can inject a `__private_module__` variable into the module to hold the mocked values. If the user called `vi.mock` with `spy: true`, we pass down the original value; otherwise, we create a simple `vi.fn()` mock.
347347+348348+If user defined a custom factory, this makes it harder to inject the code, but not impossible. When the mocked file is served, we first resolve the factory in the browser, then pass down the keys back to the server, and use them to create a placeholder module:
349349+350350+```ts
351351+const resolvedFactoryKeys = await resolveBrowserFactory(url)
352352+const mockedModule = `
353353+const __private_module__ = getFactoryReturnValue(${url})
354354+${resolvedFactoryKeys.map(key => `export const ${key} = __private_module__["${key}"]`).join('\n')}
355355+`
356356+```
357357+358358+This module can now be served back to the browser. You can inspect the code in the devtools when you run the tests.
359359+360360+## Mocking Modules Pitfalls
361361+362362+Beware that it is not possible to mock calls to methods that are called inside other methods of the same file. For example, in this code:
363363+364364+```ts [foobar.js]
365365+export function foo() {
366366+ return 'foo'
367367+}
368368+369369+export function foobar() {
370370+ return `${foo()}bar`
371371+}
372372+```
373373+374374+It is not possible to mock the `foo` method from the outside because it is referenced directly. So this code will have no effect on the `foo` call inside `foobar` (but it will affect the `foo` call in other modules):
375375+376376+```ts [foobar.test.ts]
377377+import { vi } from 'vitest'
378378+import * as mod from './foobar.js'
379379+380380+// this will only affect "foo" outside of the original module
381381+vi.spyOn(mod, 'foo')
382382+vi.mock(import('./foobar.js'), async (importOriginal) => {
383383+ return {
384384+ ...await importOriginal(),
385385+ // this will only affect "foo" outside of the original module
386386+ foo: () => 'mocked'
387387+ }
388388+})
389389+```
390390+391391+You can confirm this behavior by providing the implementation to the `foobar` method directly:
392392+393393+```ts [foobar.test.js]
394394+import * as mod from './foobar.js'
395395+396396+vi.spyOn(mod, 'foo')
397397+398398+// exported foo references mocked method
399399+mod.foobar(mod.foo)
400400+```
401401+402402+```ts [foobar.js]
403403+export function foo() {
404404+ return 'foo'
405405+}
406406+407407+export function foobar(injectedFoo) {
408408+ return injectedFoo === foo // false
409409+}
410410+```
411411+412412+This is the intended behavior, and we do not plan to implement a workaround. Consider refactoring your code into multiple files or use techniques such as [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection). We believe that making the application testable is not the responsibility of the test runner, but of the application architecture.
+114
docs/guide/mocking/requests.md
···11+# Mocking Requests
22+33+Because 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 allows you to mock `http`, `WebSocket` and `GraphQL` network requests, and is framework agnostic.
44+55+Mock Service Worker (MSW) works by intercepting the requests your tests make, allowing you to use it without changing any of your application code. In-browser, this uses the [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). In Node.js, and for Vitest, it uses the [`@mswjs/interceptors`](https://github.com/mswjs/interceptors) library. To learn more about MSW, read their [introduction](https://mswjs.io/docs/)
66+77+## Configuration
88+99+You can use it like below in your [setup file](/config/#setupfiles)
1010+1111+::: code-group
1212+1313+```js [HTTP Setup]
1414+import { afterAll, afterEach, beforeAll } from 'vitest'
1515+import { setupServer } from 'msw/node'
1616+import { http, HttpResponse } from 'msw'
1717+1818+const posts = [
1919+ {
2020+ userId: 1,
2121+ id: 1,
2222+ title: 'first post title',
2323+ body: 'first post body',
2424+ },
2525+ // ...
2626+]
2727+2828+export const restHandlers = [
2929+ http.get('https://rest-endpoint.example/path/to/posts', () => {
3030+ return HttpResponse.json(posts)
3131+ }),
3232+]
3333+3434+const server = setupServer(...restHandlers)
3535+3636+// Start server before all tests
3737+beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
3838+3939+// Close server after all tests
4040+afterAll(() => server.close())
4141+4242+// Reset handlers after each test for test isolation
4343+afterEach(() => server.resetHandlers())
4444+```
4545+4646+```js [GraphQL Setup]
4747+import { afterAll, afterEach, beforeAll } from 'vitest'
4848+import { setupServer } from 'msw/node'
4949+import { graphql, HttpResponse } from 'msw'
5050+5151+const posts = [
5252+ {
5353+ userId: 1,
5454+ id: 1,
5555+ title: 'first post title',
5656+ body: 'first post body',
5757+ },
5858+ // ...
5959+]
6060+6161+const graphqlHandlers = [
6262+ graphql.query('ListPosts', () => {
6363+ return HttpResponse.json({
6464+ data: { posts },
6565+ })
6666+ }),
6767+]
6868+6969+const server = setupServer(...graphqlHandlers)
7070+7171+// Start server before all tests
7272+beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
7373+7474+// Close server after all tests
7575+afterAll(() => server.close())
7676+7777+// Reset handlers after each test for test isolation
7878+afterEach(() => server.resetHandlers())
7979+```
8080+8181+```js [WebSocket Setup]
8282+import { afterAll, afterEach, beforeAll } from 'vitest'
8383+import { setupServer } from 'msw/node'
8484+import { ws } from 'msw'
8585+8686+const chat = ws.link('wss://chat.example.com')
8787+8888+const wsHandlers = [
8989+ chat.addEventListener('connection', ({ client }) => {
9090+ client.addEventListener('message', (event) => {
9191+ console.log('Received message from client:', event.data)
9292+ // Echo the received message back to the client
9393+ client.send(`Server received: ${event.data}`)
9494+ })
9595+ }),
9696+]
9797+9898+const server = setupServer(...wsHandlers)
9999+100100+// Start server before all tests
101101+beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
102102+103103+// Close server after all tests
104104+afterAll(() => server.close())
105105+106106+// Reset handlers after each test for test isolation
107107+afterEach(() => server.resetHandlers())
108108+```
109109+:::
110110+111111+> Configuring the server with `onUnhandledRequest: 'error'` ensures that an error is thrown whenever there is a request that does not have a corresponding request handler.
112112+113113+## More
114114+There is much more to MSW. You can access cookies and query parameters, define mock error responses, and much more! To see all you can do with MSW, read [their documentation](https://mswjs.io/docs).
+48
docs/guide/mocking/timers.md
···11+# Timers
22+33+When we test code that involves timeouts or intervals, instead of having our tests wait it out or timeout, we can speed up our tests by using "fake" timers that mock calls to `setTimeout` and `setInterval`.
44+55+See the [`vi.useFakeTimers` API section](/api/vi#vi-usefaketimers) for a more in depth detailed API description.
66+77+## Example
88+99+```js
1010+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
1111+1212+function executeAfterTwoHours(func) {
1313+ setTimeout(func, 1000 * 60 * 60 * 2) // 2 hours
1414+}
1515+1616+function executeEveryMinute(func) {
1717+ setInterval(func, 1000 * 60) // 1 minute
1818+}
1919+2020+const mock = vi.fn(() => console.log('executed'))
2121+2222+describe('delayed execution', () => {
2323+ beforeEach(() => {
2424+ vi.useFakeTimers()
2525+ })
2626+ afterEach(() => {
2727+ vi.restoreAllMocks()
2828+ })
2929+ it('should execute the function', () => {
3030+ executeAfterTwoHours(mock)
3131+ vi.runAllTimers()
3232+ expect(mock).toHaveBeenCalledTimes(1)
3333+ })
3434+ it('should not execute the function', () => {
3535+ executeAfterTwoHours(mock)
3636+ // advancing by 2ms won't trigger the func
3737+ vi.advanceTimersByTime(2)
3838+ expect(mock).not.toHaveBeenCalled()
3939+ })
4040+ it('should execute every minute', () => {
4141+ executeEveryMinute(mock)
4242+ vi.advanceTimersToNextTimer()
4343+ expect(mock).toHaveBeenCalledTimes(1)
4444+ vi.advanceTimersToNextTimer()
4545+ expect(mock).toHaveBeenCalledTimes(2)
4646+ })
4747+})
4848+```
+3-3
packages/vitest/src/integrations/vi.ts
···192192 * The call to `vi.mock` is hoisted to the top of the file, so you don't have access to variables declared in the global file scope
193193 * unless they are defined with [`vi.hoisted`](https://vitest.dev/api/vi#vi-hoisted) before this call.
194194 *
195195- * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking#modules).
195195+ * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking/modules).
196196 * @param path Path to the module. Can be aliased, if your Vitest config supports it
197197 * @param factory Mocked module factory. The result of this function will be an exports object
198198 */
···217217 *
218218 * Unlike [`vi.mock`](https://vitest.dev/api/vi#vi-mock), this method will not mock statically imported modules because it is not hoisted to the top of the file.
219219 *
220220- * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking#modules).
220220+ * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking/modules).
221221 * @param path Path to the module. Can be aliased, if your Vitest config supports it
222222 * @param factory Mocked module factory. The result of this function will be an exports object
223223 */
···254254 /**
255255 * Imports a module with all of its properties and nested properties mocked.
256256 *
257257- * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking#modules).
257257+ * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking/modules).
258258 * @example
259259 * ```ts
260260 * const example = await vi.importMock<typeof import('./example.js')>('./example.js')