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.

getMockImplementation

  • Type: (...args: any) => any

Returns current mock implementation if there is one.

If mock was created with vi.fn, it will consider passed down method as a mock implementation.

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

getMockName

  • Type: () => string

Use it to return the name given to mock with method .mockName(name).

mockClear

  • Type: () => MockInstance

Clears all information about every call. After calling it, all properties on .mock will return empty state. This method does not reset implementations. It is useful if you need to clean up mock between different assertions.

If you want this method to be called before each test automatically, you can enable clearMocks setting in config.

mockName

  • Type: (name: string) => MockInstance

Sets internal mock name. Useful to see the name of the mock if assertion fails.

mockImplementation

  • Type: (fn: Function) => MockInstance

Accepts a function that will be used as an implementation of the mock.

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

  • Type: (fn: Function) => MockInstance

Accepts a function that will be used as mock's implementation during the next call. Can be chained so that multiple function calls produce different results.

ts
const myMockFn = vi
  .fn()
  .mockImplementationOnce(() => true)
  .mockImplementationOnce(() => false)

myMockFn() // true
myMockFn() // false

When the mocked function runs out of implementations, it will invoke the default implementation that was 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

  • Type: (fn: Function, callback: () => void) => MockInstance
  • Type: (fn: Function, callback: () => Promise<unknown>) => Promise<MockInstance>

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

  • Type: (value: any) => MockInstance

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 "Async error"

mockRejectedValueOnce

  • Type: (value: any) => MockInstance

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

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

await asyncMock() // first call
await asyncMock() // throws "Async error"

mockReset

  • Type: () => MockInstance

Does what mockClear does and makes inner implementation an empty function (returning undefined when invoked). This also resets all "once" implementations. This is useful when you want to completely reset a mock to the default state.

If you want this method to be called before each test automatically, you can enable mockReset setting in config.

mockRestore

  • Type: () => MockInstance

Does what mockReset does and restores inner implementation to the original function.

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

If you want this method to be called before each test automatically, you can enable restoreMocks setting in config.

mockResolvedValue

  • Type: (value: any) => MockInstance

Accepts a value that will be resolved when async function is called.

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

await asyncMock() // 42

mockResolvedValueOnce

  • Type: (value: any) => MockInstance

Accepts a value that will be resolved during the next function call. If chained, every consecutive call will resolve 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

  • Type: () => MockInstance

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

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

mockReturnValue

  • Type: (value: any) => MockInstance

Accepts a value that will be returned whenever the mock function is called.

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

mockReturnValueOnce

  • Type: (value: any) => MockInstance

Accepts a value that will be returned during the next function call. If chained, every consecutive call will return the specified value.

When there are no more mockReturnValueOnce values to use, mock will fallback to previously defined implementation if there is one.

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

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

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

mock.results

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

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

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

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

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.