Mocking
Mocking functions
Mock functions (or "spies") observe functions, that are invoked in some other code, allowing you to test its arguments, output or even redeclare its implementation.
We use 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, but the return result of vi.fn()
is callable.
vi.fn
Type: (fn: Function) => CallableMockInstance
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. If no function is given, mock will return undefined
, when invoked.
const getApples = vi.fn(() => 0)
getApples()
expect(getApples).toHaveBeenCalled()
expect(getApples).toHaveReturnedWith(0)
getApples.mockReturnOnce(5)
const res = getApples()
expect(res).toBe(5)
expect(getApples).toHaveReturnedNthTimeWith(1, 5)
vi.spyOn
Type: <T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance
Creates a spy on a method or getter/setter of an object.
let apples = 0
const obj = {
getApples: () => 13,
}
const spy = vi.spyOn(obj, 'getApples').mockImplementation(() => apples)
apples = 1
expect(obj.getApples()).toBe(1)
expect(spy).toHaveBeenCalled()
expect(spy).toHaveReturnedWith(1)
Mock methods
mockName
Type: (name: string) => MockInstance
Sets internal mock name. Useful to see what mock has failed the assertion.
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, spy.mock.calls
, spy.mock.returns
will return empty arrays. It is useful if you need to clean up spy between different assertions.
If you want this method to be called before each test automatically, you can enable clearMocks
setting in config.
mockReset
Type: () => MockInstance
Does what mockClear
does and makes inner implementation as an empty function (returning undefined
, when invoked). This is useful when you want to completely reset a mock back to its initial 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 mockRestore
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.
mockImplementation
Type: (fn: Function) => MockInstance
Accepts a function that will be used as an implementation of the mock.
For example:
const mockFn = vi.fn().mockImplementation(apples => 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 an implementation of the mock for one call to the mocked function. Can be chained so that multiple function calls produce different results.
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:
const myMockFn = vi
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
mockReturnThis
Type: () => MockInstance
Sets inner implementation to return this
context.
mockReturnValue
Type: (value: any) => MockInstance
Accepts a value that will be returned whenever the mock function is called.
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 whenever mock function is invoked. If chained, every consecutive call will return passed value. When there are no more mockReturnValueOnce
values to use, calls a function specified by mockImplementation
or other mockReturn*
methods.
const myMockFn = vi
.fn()
.mockReturnValue('default')
.mockReturnValueOnce('first call')
.mockReturnValueOnce('second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
mockResolvedValue
Type: (value: any) => MockInstance
Accepts a value that will be resolved, when async function will be called.
test('async test', async () => {
const asyncMock = vi.fn().mockResolvedValue(43);
await asyncMock(); // 43
});
mockResolvedValueOnce
Type: (value: any) => MockInstance
Accepts a value that will be resolved for one call to the mock function. If chained, every consecutive call will resolve passed value.
test('async test', async () => {
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
});
mockRejectedValue
Type: (value: any) => MockInstance
Accepts an error that will be rejected, when async function will be called.
test('async test', async () => {
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 for one call to the mock function. If chained, every consecutive call will reject passed value.
test('async test', async () => {
const asyncMock = vi
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error'));
await asyncMock(); // first call
await asyncMock(); // throws "Async error"
});
Mock properties
mock.calls
This is an array containing all arguments for each call. One item of the array is arguments of that call.
If a function was invoked twice with the following arguments fn(arg1, arg2)
, fn(arg3, arg4)
in that order, then mock.calls
will be:
[
['arg1', 'arg2'],
['arg3', 'arg4'],
];
mock.results
This is an array containing all values, that were returned
from 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 returned value or thrown error.
If function returned 'result1
, then threw and error, then mock.results
will be:
[
{
type: 'return',
value: 'result',
},
{
type: 'throw',
value: Error,
},
];
mock.instances
Currently, this property is not implemented.