Skip to content

Mock Functions

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:

js
import { vi } from 'vitest'

const fn = vi.fn()
fn('hello world')
fn.mock.calls[0] === ['hello world']

const market = {
  getApples: () => 100
}

const getApplesSpy = vi.spyOn(market, 'getApples')
market.getApples()
getApplesSpy.mock.calls.length === 1

You should use mock assertions (e.g., toHaveBeenCalled) on expect to assert mock result. 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>.

getMockImplementation

ts
function getMockImplementation(): T | undefined

Returns current mock implementation if there is one.

If the mock was created with vi.fn, it will use the provided method as the mock implementation.

If the mock was created with vi.spyOn, it will return undefined unless a custom implementation is provided.

getMockName

ts
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().

mockClear

ts
function mockClear(): MockInstance<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.

To automatically call this method before each test, enable the clearMocks setting in the configuration.

mockName

ts
function mockName(name: string): MockInstance<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>

Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function.

ts
const mockFn = vi.fn().mockImplementation((apples: number) => apples + 1)
// or: vi.fn(apples => apples + 1);

const NelliesBucket = mockFn(0)
const BobsBucket = mockFn(1)

NelliesBucket === 1 // true
BobsBucket === 2 // true

mockFn.mock.calls[0][0] === 0 // true
mockFn.mock.calls[1][0] === 1 // true

mockImplementationOnce

ts
function mockImplementationOnce(fn: T): MockInstance<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.

ts
const myMockFn = vi
  .fn()
  .mockImplementationOnce(() => true) // 1st call
  .mockImplementationOnce(() => false) // 2nd call

myMockFn() // 1st call: true
myMockFn() // 2nd call: false

When the mocked function runs out of implementations, it will invoke the default implementation set with vi.fn(() => defaultValue) or .mockImplementation(() => defaultValue) if they were called:

ts
const myMockFn = vi
  .fn(() => 'default')
  .mockImplementationOnce(() => 'first call')
  .mockImplementationOnce(() => 'second call')

// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn())

withImplementation

ts
function withImplementation(
  fn: T,
  cb: () => void
): MockInstance<T>
function withImplementation(
  fn: T,
  cb: () => Promise<void>
): Promise<MockInstance<T>>

Overrides the original mock implementation temporarily while the callback is being executed.

js
const myMockFn = vi.fn(() => 'original')

myMockFn.withImplementation(() => 'temp', () => {
  myMockFn() // 'temp'
})

myMockFn() // 'original'

Can be used with an asynchronous callback. The method has to be awaited to use the original implementation afterward.

ts
test('async callback', () => {
  const myMockFn = vi.fn(() => 'original')

  // We await this call since the callback is async
  await myMockFn.withImplementation(
    () => 'temp',
    async () => {
      myMockFn() // 'temp'
    },
  )

  myMockFn() // 'original'
})

Note that this method takes precedence over the mockImplementationOnce.

mockRejectedValue

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

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

ts
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'))

await asyncMock() // throws Error<'Async error'>

mockRejectedValueOnce

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

Accepts a value that will be rejected during the next function call. If chained, each consecutive call will reject the specified value.

ts
const asyncMock = vi
  .fn()
  .mockResolvedValueOnce('first call')
  .mockRejectedValueOnce(new Error('Async error'))

await asyncMock() // 'first call'
await asyncMock() // throws Error<'Async error'>

mockReset

ts
function mockReset(): MockInstance<T>

Performs the same actions as mockClear and sets the inner implementation to an empty function (returning undefined when invoked). This also resets all "once" implementations. It is useful for completely resetting a mock to its default state.

To automatically call this method before each test, enable the mockReset setting in the configuration.

mockRestore

ts
function mockRestore(): MockInstance<T>

Performs the same actions as mockReset and restores the inner implementation to the original function.

Note that restoring a mock created with vi.fn() will set the implementation to an empty function that returns undefined. Restoring a mock created with vi.fn(impl) will restore the implementation to impl.

To automatically call this method before each test, enable the restoreMocks setting in the configuration.

mockResolvedValue

ts
function mockResolvedValue(value: Awaited<ReturnType<T>>): MockInstance<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.

ts
const asyncMock = vi.fn().mockResolvedValue(42)

await asyncMock() // 42

mockResolvedValueOnce

ts
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): MockInstance<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.

ts
const asyncMock = vi
  .fn()
  .mockResolvedValue('default')
  .mockResolvedValueOnce('first call')
  .mockResolvedValueOnce('second call')

await asyncMock() // first call
await asyncMock() // second call
await asyncMock() // default
await asyncMock() // default

mockReturnThis

ts
function mockReturnThis(): MockInstance<T>

Use this if you need to return the this context from the method without invoking the actual implementation. This is a shorthand for:

ts
spy.mockImplementation(function () {
  return this
})

mockReturnValue

ts
function mockReturnValue(value: ReturnType<T>): MockInstance<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.

ts
const mock = vi.fn()
mock.mockReturnValue(42)
mock() // 42
mock.mockReturnValue(43)
mock() // 43

mockReturnValueOnce

ts
function mockReturnValueOnce(value: ReturnType<T>): MockInstance<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.

When the mocked function runs out of implementations, it will invoke the default implementation set with vi.fn(() => defaultValue) or .mockImplementation(() => defaultValue) if they were called:

ts
const myMockFn = vi
  .fn()
  .mockReturnValue('default')
  .mockReturnValueOnce('first call')
  .mockReturnValueOnce('second call')

// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn())

mock.calls

ts
const calls: Parameters<T>[]

This is an array containing all arguments for each call. One item of the array is the arguments of that call.

js
const fn = vi.fn()

fn('arg1', 'arg2')
fn('arg3')

fn.mock.calls === [
  ['arg1', 'arg2'], // first call
  ['arg3'], // second call
]

mock.lastCall

ts
const lastCall: Parameters<T> | undefined

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

mock.results

ts
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.
   */
  value: T
}

interface MockResultIncomplete {
  type: 'incomplete'
  value: undefined
}

interface MockResultThrow {
  type: 'throw'
  /**
   * An error that was thrown during function execution.
   */
  value: any
}

type MockResult<T> =
  | MockResultReturn<T>
  | MockResultThrow
  | MockResultIncomplete

const results: MockResult<ReturnType<T>>[]

This is an array containing all values that were returned from the function. One item of the array is an object with properties type and value. Available types are:

  • 'return' - function returned without throwing.
  • 'throw' - function threw a value.

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.

js
const fn = vi.fn()
  .mockReturnValueOnce('result')
  .mockImplementationOnce(() => { throw new Error('thrown error') })

const result = fn() // returned 'result'

try {
  fn() // threw Error
}
catch {}

fn.mock.results === [
  // first result
  {
    type: 'return',
    value: 'result',
  },
  // last result
  {
    type: 'throw',
    value: Error,
  },
]

mock.settledResults

ts
interface MockSettledResultFulfilled<T> {
  type: 'fulfilled'
  value: T
}

interface MockSettledResultRejected {
  type: 'rejected'
  value: any
}

export type MockSettledResult<T> =
  | MockSettledResultFulfilled<T>
  | MockSettledResultRejected

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

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

This array will be empty if the function was never resolved or rejected.

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

const result = fn()

fn.mock.settledResults === []

await result

fn.mock.settledResults === [
  {
    type: 'fulfilled',
    value: 'result',
  },
]

mock.invocationCallOrder

ts
const invocationCallOrder: number[]

This property returns the order of the mock function's execution. It is an array of numbers that are shared between all defined mocks.

js
const fn1 = vi.fn()
const fn2 = vi.fn()

fn1()
fn2()
fn1()

fn1.mock.invocationCallOrder === [1, 3]
fn2.mock.invocationCallOrder === [2]

mock.contexts

ts
const contexts: ThisParameterType<T>[]

This property is an array of this values used during each call to the mock function.

js
const fn = vi.fn()
const context = {}

fn.apply(context)
fn.call(context)

fn.mock.contexts[0] === context
fn.mock.contexts[1] === context

mock.instances

ts
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.

WARNING

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

js
const MyClass = vi.fn()
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:

js
const Spy = vi.fn(() => ({ method: vi.fn() }))
const a = new Spy()

Spy.mock.instances[0] !== a
Spy.mock.results[0] === a

Released under the MIT License.