Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
716e207
fix!: rewrite spying implementation to make module mocking more logical
sheremet-va Jul 30, 2025
2082369
chore: lint
sheremet-va Jul 30, 2025
f657700
fix: copy static props, restore some previous behaviours
sheremet-va Jul 30, 2025
d3f87e4
fix: do not copy getters
sheremet-va Jul 30, 2025
bfda423
fix: keep getters and setters in spy mode
sheremet-va Jul 30, 2025
86eb9b1
chore: lint
sheremet-va Jul 30, 2025
6a1ba96
fix: keep using the original name in vi.spyOn
sheremet-va Jul 30, 2025
b3f3e22
docs: add migration guide
sheremet-va Jul 30, 2025
3cc251b
chore: remove debugging comment
sheremet-va Jul 30, 2025
fde9888
test: fix browser snapshot test
sheremet-va Jul 30, 2025
9bae554
fix: don't allow overriding mock.mock
sheremet-va Jul 30, 2025
f7d0227
docs: add example of mock.mock to jest differences
sheremet-va Jul 30, 2025
97c01d8
chore: remove tinyspy from dependencies
sheremet-va Jul 30, 2025
bec02bf
refactor: cleanup
sheremet-va Jul 31, 2025
5f12b6a
docs: cleanup
sheremet-va Jul 31, 2025
0e14a62
test: more test
sheremet-va Jul 31, 2025
2a03266
docs: add mocking modules guide
sheremet-va Jul 31, 2025
b6932df
fix: don't empty array if `spy` is set to `true`
sheremet-va Jul 31, 2025
46b4846
chore: fix links
sheremet-va Jul 31, 2025
93cb84c
docs: cleanup
sheremet-va Jul 31, 2025
c1e2252
docs: cleanup
sheremet-va Jul 31, 2025
1cb2d0d
chore: add a log for console.warn
sheremet-va Aug 1, 2025
4bb8b5e
docs: add virtual modules
sheremet-va Aug 1, 2025
35c3aef
docs: update mocking docs
sheremet-va Aug 1, 2025
6c2a4d5
test: don't use using
sheremet-va Aug 1, 2025
952755d
docs: remove irrelevant comment
sheremet-va Aug 1, 2025
72a0634
docs: fix link
sheremet-va Aug 1, 2025
5a32529
docs: cleanup
sheremet-va Aug 1, 2025
34adde5
chore: cleanup
sheremet-va Aug 1, 2025
4f48ca9
Merge branch 'main' of github.com:vitest-dev/vitest into fix/mocking-…
sheremet-va Aug 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,41 @@ function guide(): DefaultTheme.SidebarItem[] {
{
text: 'Mocking',
link: '/guide/mocking',
collapsed: true,
items: [
{
text: 'Mocking Dates',
link: '/guide/mocking#dates',
},
{
text: 'Mocking Functions',
link: '/guide/mocking#functions',
},
{
text: 'Mocking Globals',
link: '/guide/mocking#globals',
},
{
text: 'Mocking Modules',
link: '/guide/mocking-modules',
},
{
text: 'Mocking File System',
link: '/guide/mocking#file-system',
},
{
text: 'Mocking Requests',
link: '/guide/mocking#requests',
},
{
text: 'Mocking Timers',
link: '/guide/mocking#timers',
},
{
text: 'Mocking Classes',
link: '/guide/mocking#classes',
},
],
},
{
text: 'Parallelism',
Expand Down Expand Up @@ -586,7 +621,7 @@ function api(): DefaultTheme.SidebarItem[] {
link: '/api/',
},
{
text: 'Mock Functions',
text: 'Mocks',
link: '/api/mock',
},
{
Expand Down
84 changes: 48 additions & 36 deletions docs/api/mock.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Mock Functions
# Mocks

You can create a mock function to track its execution with `vi.fn` method. If you want to track a method on an already created object, you can use `vi.spyOn` method:
You can create a mock function or a class to track its execution with the `vi.fn` method. If you want to track a property on an already created object, you can use the `vi.spyOn` method:

```js
import { vi } from 'vitest'
Expand All @@ -18,7 +18,7 @@ market.getApples()
getApplesSpy.mock.calls.length === 1
```

You should use mock assertions (e.g., [`toHaveBeenCalled`](/api/expect#tohavebeencalled)) on [`expect`](/api/expect) to assert mock result. This API reference describes available properties and methods to manipulate mock behavior.
You should use mock assertions (e.g., [`toHaveBeenCalled`](/api/expect#tohavebeencalled)) on [`expect`](/api/expect) to assert mock results. This API reference describes available properties and methods to manipulate mock behavior.

::: tip
The custom function implementation in the types below is marked with a generic `<T>`.
Expand All @@ -30,7 +30,7 @@ The custom function implementation in the types below is marked with a generic `
function getMockImplementation(): T | undefined
```

Returns current mock implementation if there is one.
Returns the current mock implementation if there is one.

If the mock was created with [`vi.fn`](/api/vi#vi-fn), it will use the provided method as the mock implementation.

Expand All @@ -42,12 +42,12 @@ If the mock was created with [`vi.spyOn`](/api/vi#vi-spyon), it will return `und
function getMockName(): string
```

Use it to return the name assigned to the mock with the `.mockName(name)` method. By default, it will return `vi.fn()`.
Use it to return the name assigned to the mock with the `.mockName(name)` method. By default, `vi.fn()` mocks will return `'vi.fn()'`, while spies created with `vi.spyOn` will keep the original name.

## mockClear

```ts
function mockClear(): MockInstance<T>
function mockClear(): Mock<T>
```

Clears all information about every call. After calling it, all properties on `.mock` will return to their initial state. This method does not reset implementations. It is useful for cleaning up mocks between different assertions.
Expand All @@ -72,15 +72,15 @@ To automatically call this method before each test, enable the [`clearMocks`](/c
## mockName

```ts
function mockName(name: string): MockInstance<T>
function mockName(name: string): Mock<T>
```

Sets the internal mock name. This is useful for identifying the mock when an assertion fails.

## mockImplementation

```ts
function mockImplementation(fn: T): MockInstance<T>
function mockImplementation(fn: T): Mock<T>
```

Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function.
Expand All @@ -102,7 +102,7 @@ mockFn.mock.calls[1][0] === 1 // true
## mockImplementationOnce

```ts
function mockImplementationOnce(fn: T): MockInstance<T>
function mockImplementationOnce(fn: T): Mock<T>
```

Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. This method can be chained to produce different results for multiple function calls.
Expand Down Expand Up @@ -135,11 +135,11 @@ console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn())
function withImplementation(
fn: T,
cb: () => void
): MockInstance<T>
): Mock<T>
function withImplementation(
fn: T,
cb: () => Promise<void>
): Promise<MockInstance<T>>
): Promise<Mock<T>>
```

Overrides the original mock implementation temporarily while the callback is being executed.
Expand Down Expand Up @@ -177,10 +177,10 @@ Note that this method takes precedence over the [`mockImplementationOnce`](#mock
## mockRejectedValue

```ts
function mockRejectedValue(value: unknown): MockInstance<T>
function mockRejectedValue(value: unknown): Mock<T>
```

Accepts an error that will be rejected when async function is called.
Accepts an error that will be rejected when an async function is called.

```ts
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'))
Expand All @@ -191,7 +191,7 @@ await asyncMock() // throws Error<'Async error'>
## mockRejectedValueOnce

```ts
function mockRejectedValueOnce(value: unknown): MockInstance<T>
function mockRejectedValueOnce(value: unknown): Mock<T>
```

Accepts a value that will be rejected during the next function call. If chained, each consecutive call will reject the specified value.
Expand All @@ -209,14 +209,13 @@ await asyncMock() // throws Error<'Async error'>
## mockReset

```ts
function mockReset(): MockInstance<T>
function mockReset(): Mock<T>
```

Does what [`mockClear`](#mockClear) does and resets inner implementation to the original function.
This also resets all "once" implementations.
Does what [`mockClear`](#mockClear) does and resets the mock implementation. This also resets all "once" implementations.

Note that resetting a mock from `vi.fn()` will set implementation to an empty function that returns `undefined`.
resetting a mock from `vi.fn(impl)` will restore implementation to `impl`.
Note that resetting a mock from `vi.fn()` will set the implementation to an empty function that returns `undefined`.
Resetting a mock from `vi.fn(impl)` will reset the implementation to `impl`.

This is useful when you want to reset a mock to its original state.

Expand All @@ -241,13 +240,12 @@ To automatically call this method before each test, enable the [`mockReset`](/co
## mockRestore

```ts
function mockRestore(): MockInstance<T>
function mockRestore(): Mock<T>
```

Does what [`mockReset`](#mockReset) does and restores original descriptors of spied-on objects.
Does what [`mockReset`](#mockreset) does and restores the original descriptors of spied-on objects, if the mock was created with [`vi.spyOn`](/api/vi#vi-spyon).

Note that restoring a mock from `vi.fn()` will set implementation to an empty function that returns `undefined`.
Restoring a mock from `vi.fn(impl)` will restore implementation to `impl`.
`mockRestore` on a `vi.fn()` mock is identical to [`mockReset`](#mockreset).

```ts
const person = {
Expand All @@ -270,7 +268,7 @@ To automatically call this method before each test, enable the [`restoreMocks`](
## mockResolvedValue

```ts
function mockResolvedValue(value: Awaited<ReturnType<T>>): MockInstance<T>
function mockResolvedValue(value: Awaited<ReturnType<T>>): Mock<T>
```

Accepts a value that will be resolved when the async function is called. TypeScript will only accept values that match the return type of the original function.
Expand All @@ -284,7 +282,7 @@ await asyncMock() // 42
## mockResolvedValueOnce

```ts
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): MockInstance<T>
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): Mock<T>
```

Accepts a value that will be resolved during the next function call. TypeScript will only accept values that match the return type of the original function. If chained, each consecutive call will resolve the specified value.
Expand All @@ -305,7 +303,7 @@ await asyncMock() // default
## mockReturnThis

```ts
function mockReturnThis(): MockInstance<T>
function mockReturnThis(): Mock<T>
```

Use this if you need to return the `this` context from the method without invoking the actual implementation. This is a shorthand for:
Expand All @@ -319,7 +317,7 @@ spy.mockImplementation(function () {
## mockReturnValue

```ts
function mockReturnValue(value: ReturnType<T>): MockInstance<T>
function mockReturnValue(value: ReturnType<T>): Mock<T>
```

Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function.
Expand All @@ -335,7 +333,7 @@ mock() // 43
## mockReturnValueOnce

```ts
function mockReturnValueOnce(value: ReturnType<T>): MockInstance<T>
function mockReturnValueOnce(value: ReturnType<T>): Mock<T>
```

Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function.
Expand Down Expand Up @@ -379,7 +377,7 @@ fn.mock.calls === [
const lastCall: Parameters<T> | undefined
```

This contains the arguments of the last call. If mock wasn't called, it will return `undefined`.
This contains the arguments of the last call. If the mock wasn't called, it will return `undefined`.

## mock.results

Expand All @@ -388,7 +386,7 @@ interface MockResultReturn<T> {
type: 'return'
/**
* The value that was returned from the function.
* If function returned a Promise, then this will be a resolved value.
* If the function returned a Promise, then this will be a resolved value.
*/
value: T
}
Expand Down Expand Up @@ -418,6 +416,7 @@ This is an array containing all values that were `returned` from the function. O

- `'return'` - function returned without throwing.
- `'throw'` - function threw a value.
- `'incomplete'` - the function did not finish running yet.

The `value` property contains the returned value or thrown error. If the function returned a `Promise`, then `result` will always be `'return'` even if the promise was rejected.

Expand Down Expand Up @@ -450,6 +449,11 @@ fn.mock.results === [
## mock.settledResults

```ts
interface MockSettledResultIncomplete {
type: 'incomplete'
value: undefined
}

interface MockSettledResultFulfilled<T> {
type: 'fulfilled'
value: T
Expand All @@ -463,20 +467,28 @@ interface MockSettledResultRejected {
export type MockSettledResult<T>
= | MockSettledResultFulfilled<T>
| MockSettledResultRejected
| MockSettledResultIncomplete

const settledResults: MockSettledResult<Awaited<ReturnType<T>>>[]
```

An array containing all values that were `resolved` or `rejected` from the function.
An array containing all values that were resolved or rejected by the function.

If the function returned non-promise values, the `value` will be kept as is, but the `type` will still says `fulfilled` or `rejected`.

This array will be empty if the function was never resolved or rejected.
Until the value is resolved or rejected, the `settledResult` type will be `incomplete`.

```js
const fn = vi.fn().mockResolvedValueOnce('result')

const result = fn()

fn.mock.settledResults === []
fn.mock.settledResults === [
{
type: 'incomplete',
value: undefined,
},
]

await result

Expand Down Expand Up @@ -533,10 +545,10 @@ fn.mock.contexts[1] === context
const instances: ReturnType<T>[]
```

This property is an array containing all instances that were created when the mock was called with the `new` keyword. Note that this is an actual context (`this`) of the function, not a return value.
This property is an array containing all instances that were created when the mock was called with the `new` keyword. Note that this is the actual context (`this`) of the function, not a return value.

::: warning
If mock was instantiated with `new MyClass()`, then `mock.instances` will be an array with one value:
If the mock was instantiated with `new MyClass()`, then `mock.instances` will be an array with one value:

```js
const MyClass = vi.fn()
Expand All @@ -545,7 +557,7 @@ const a = new MyClass()
MyClass.mock.instances[0] === a
```

If you return a value from constructor, it will not be in `instances` array, but instead inside `results`:
If you return a value from the constructor, it will not be in the `instances` array, but instead inside `results`:

```js
const Spy = vi.fn(() => ({ method: vi.fn() }))
Expand Down
Loading
Loading