Mock-функции
Вы можете создать mock-функцию для отслеживания её вызовов с помощью метода vi.fn
. Если вы хотите отслеживать метод существующего объекта, вы можете использовать метод vi.spyOn
:
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;
Для проверки результатов работы mock-функций используйте утверждения mock (например, toHaveBeenCalled
) в expect
. Этот справочник API описывает доступные свойства и методы для управления поведением mock-функций.
getMockImplementation
- Тип:
(...args: any) => any
Возвращает текущую реализацию mock-функции, если она задана.
Если mock-функция была создана с помощью vi.fn
, она будет использовать переданную функцию в качестве реализации.
Если mock-функция была создана с помощью vi.spyOn
, она вернет undefined
, если пользовательская реализация не была предоставлена.
getMockName
- Тип:
() => string
Используйте этот метод, чтобы получить имя, присвоенное mock-функции с помощью метода .mockName(name)
.
mockClear
- Тип:
() => MockInstance
Очищает информацию обо всех вызовах mock-функции. После вызова все свойства в .mock
будут возвращать значения по умолчанию. Это полезно для очистки mock-функции между различными утверждениями.
Если вы хотите, чтобы этот метод вызывался автоматически перед каждым тестом, вы можете включить параметр clearMocks
в конфигурации.
mockName
- Тип:
(name: string) => MockInstance
Устанавливает внутреннее имя mock-функции. Это полезно для идентификации mock-функции при сбое утверждения.
mockImplementation
- Тип:
(fn: Function) => MockInstance
Принимает функцию, которая будет использоваться в качестве реализации mock-функции.
import { vi } from 'vitest';
// ---cut---
const mockFn = vi.fn().mockImplementation(apples => apples + 1);
// или: 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
- Тип:
(fn: Function) => MockInstance
Принимает функцию, которая будет использоваться в качестве реализации mock-функции только при следующем вызове. Можно объединять в цепочку, чтобы последовательные вызовы функций давали разные результаты.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true)
.mockImplementationOnce(() => false);
myMockFn(); // true
myMockFn(); // false
Когда у mock-функции заканчиваются реализации, установленные с помощью mockImplementationOnce
, она вызывает реализацию по умолчанию, которая была установлена с помощью vi.fn(() => defaultValue)
или .mockImplementation(() => defaultValue)
, если они были вызваны ранее.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
withImplementation
- Тип:
(fn: Function, callback: () => void) => MockInstance
- Тип:
(fn: Function, callback: () => Promise<unknown>) => Promise<MockInstance>
Временно заменяет исходную реализацию mock-функции на время выполнения обратного вызова.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
Может использоваться с асинхронным обратным вызовом. Чтобы использовать исходную реализацию впоследствии, необходимо дождаться завершения асинхронного обратного вызова.
test('async callback', () => {
const myMockFn = vi.fn(() => 'original');
// Мы ожидаем этот вызов, так как обратный вызов является асинхронным
await myMockFn.withImplementation(
() => 'temp',
async () => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
});
Обратите внимание, что этот метод имеет приоритет над mockImplementationOnce
.
mockRejectedValue
- Тип:
(value: any) => MockInstance
Принимает значение, которое будет отклонено при вызове асинхронной mock-функции.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws "Async error"
mockRejectedValueOnce
- Тип:
(value: any) => MockInstance
Принимает значение, которое будет отклонено при следующем вызове mock-функции. При объединении в цепочку, каждый последующий вызов будет отклонять указанное значение.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error'));
await asyncMock(); // first call
await asyncMock(); // throws "Async error"
mockReset
- Тип:
() => MockInstance
Делает то же, что и mockClear
, и устанавливает внутреннюю реализацию в пустую функцию (возвращающую undefined
при вызове). Это также сбрасывает все реализации, установленные с помощью "once". Это полезно, когда вы хотите полностью сбросить mock-функцию в состояние по умолчанию.
Если вы хотите, чтобы этот метод вызывался автоматически перед каждым тестом, вы можете включить параметр mockReset
в конфигурации.
mockRestore
- Тип:
() => MockInstance
Делает то же, что и mockReset
, и возвращает внутреннюю реализацию к исходной функции.
Обратите внимание, что восстановление mock-функции, созданной с помощью vi.fn()
, установит реализацию в пустую функцию, которая возвращает undefined
. Восстановление vi.fn(impl)
восстановит реализацию до impl
.
Если вы хотите, чтобы этот метод вызывался автоматически перед каждым тестом, вы можете включить параметр restoreMocks
в конфигурации.
mockResolvedValue
- Тип:
(value: any) => MockInstance
Принимает значение, которое будет возвращено успешно (resolved) при вызове асинхронной mock-функции.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
- Тип:
(value: any) => MockInstance
Принимает значение, которое будет возвращено успешно (resolved) при следующем вызове mock-функции. Если объединено в цепочку, каждый последующий вызов будет возвращать указанное значение.
import { vi } from 'vitest';
// ---cut---
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
- Тип:
() => MockInstance
Используйте это, если вам нужно вернуть контекст this
из метода, не вызывая фактическую реализацию. Это сокращение для:
spy.mockImplementation(function () {
return this;
});
mockReturnValue
- Тип:
(value: any) => MockInstance
Принимает значение, которое будет возвращаться при каждом вызове mock-функции.
import { vi } from 'vitest';
// ---cut---
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
- Тип:
(value: any) => MockInstance
Принимает значение, которое будет возвращено во время следующего вызова функции. Если объединено в цепочку, каждый последующий вызов будет возвращать указанное значение.
Когда больше нет значений mockReturnValueOnce
для использования, mock-функция вернется к ранее определенной реализации, если она есть.
import { vi } from 'vitest';
// ---cut---
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
Это массив, содержащий все аргументы для каждого вызова mock-функции. Каждый элемент массива представляет собой аргументы соответствующего вызова.
const fn = vi.fn();
fn('arg1', 'arg2');
fn('arg3');
fn.mock.calls ===
[
['arg1', 'arg2'], // first call
['arg3'], // second call
];
mock.lastCall
Содержит аргументы последнего вызова mock-функции. Если mock-функция не была вызвана, вернет undefined
.
mock.results
Это массив, содержащий все результаты, возвращённые mock-функцией. Каждый элемент массива - это объект со свойствами type
и value
. Доступные типы:
'return'
- функция завершилась успешно.'throw'
- функция выбросила исключение.
Свойство value
содержит возвращенное значение или выброшенную ошибку. Если функция вернула promise, value
будет разрешённым значением, а не самим Promise
, если разрешение произошло.
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.invocationCallOrder
Порядок выполнения вызовов mock-функций. Возвращает массив чисел, которые являются общими для всех определенных mock-функций.
const fn1 = vi.fn();
const fn2 = vi.fn();
fn1();
fn2();
fn1();
fn1.mock.invocationCallOrder === [1, 3];
fn2.mock.invocationCallOrder === [2];
mock.instances
Это массив, содержащий все экземпляры, которые были созданы при вызове mock-функции с ключевым словом new
. Обратите внимание, что это фактический контекст (this
) функции, а не возвращаемое ею значение.
WARNING
Если mock-функция была создана с помощью new MyClass()
, то mock.instances
будет массивом с одним значением:
const MyClass = vi.fn();
const a = new MyClass();
MyClass.mock.instances[0] === a;
Если вы возвращаете значение из конструктора, его не будет в массиве instances
, а вместо этого внутри results
:
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();
Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;