Мок-функции
Вы можете создать мок-функцию для отслеживания ее вызовов с помощью метода 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;
Для проверки результатов мока следует использовать соответствующие утверждения (например, toHaveBeenCalled
) с expect
. В этом справочнике API описаны доступные свойства и методы для управления поведением мока.
TIP
Реализация пользовательской функции в типах ниже помечена как универсальная <T>
.
getMockImplementation
function getMockImplementation(): T | undefined;
Возвращает текущую реализацию мока, если таковая имеется.
Если мок был создан с помощью vi.fn
, он будет использовать предоставленный метод в качестве реализации мока.
Если мок был создан с помощью vi.spyOn
, он вернет undefined
, если не была предоставлена пользовательская реализация.
getMockName
function getMockName(): string;
Используйте его для получения имени, присвоенного моку с помощью метода .mockName(name)
. По умолчанию возвращается vi.fn()
.
mockClear
function mockClear(): MockInstance<T>;
Очищает всю информацию о каждом вызове. После вызова все свойства .mock
вернутся в исходное состояние. Этот метод не сбрасывает реализации. Он полезен для очистки моков между различными утверждениями.
Чтобы автоматически вызывать этот метод перед каждым тестом, включите настройку clearMocks
в конфигурации.
mockName
function mockName(name: string): MockInstance<T>;
Устанавливает внутреннее имя мока. Это полезно для идентификации мока в случае сбоя утверждения.
mockImplementation
function mockImplementation(fn: T): MockInstance<T>;
Принимает функцию для использования в качестве реализации мока. TypeScript ожидает, что аргументы и тип возвращаемого значения будут соответствовать аргументам и типу возвращаемого значения исходной функции.
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
function mockImplementationOnce(fn: T): MockInstance<T>;
Принимает функцию, которая будет использоваться в качестве реализации мока. TypeScript ожидает, что аргументы и тип возвращаемого значения будут соответствовать аргументам и типу возвращаемого значения исходной функции. Этот метод можно вызывать цепочкой для получения разных результатов при нескольких вызовах функции.
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true) // 1st call
.mockImplementationOnce(() => false); // 2nd call
myMockFn(); // 1st call: true
myMockFn(); // 2nd call: false
Когда у мок-функции заканчиваются реализации, она вызовет реализацию по умолчанию, установленную с помощью vi.fn(() => defaultValue)
или .mockImplementation(() => defaultValue)
, если они были вызваны.
const myMockFn = vi
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
withImplementation
function withImplementation(fn: T, cb: () => void): MockInstance<T>;
function withImplementation(
fn: T,
cb: () => Promise<void>
): Promise<MockInstance<T>>;
Временно переопределяет исходную реализацию мока на время выполнения колбэка.
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
Может использоваться с асинхронным колбэком. Метод должен быть ожидаемым, чтобы после этого использовать исходную реализацию.
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'
});
Обратите внимание, что этот метод имеет приоритет над mockImplementationOnce
.
mockRejectedValue
function mockRejectedValue(value: unknown): MockInstance<T>;
Принимает ошибку, которая будет отклонена при вызове асинхронной функции.
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws Error<'Async error'>
mockRejectedValueOnce
function mockRejectedValueOnce(value: unknown): MockInstance<T>;
Принимает значение, которое будет отклонено при следующем вызове функции. При цепочке вызовов каждый последующий вызов будет отклонять указанное значение.
const asyncMock = vi
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error'));
await asyncMock(); // 'first call'
await asyncMock(); // throws Error<'Async error'>
mockReset
function mockReset(): MockInstance<T>;
Выполняет те же действия, что и mockClear
, и устанавливает внутреннюю реализацию в пустую функцию (возвращающую undefined
при вызове). Это также сбрасывает все реализации "once". Это полезно для полного сброса мока к его состоянию по умолчанию.
Чтобы автоматически вызывать этот метод перед каждым тестом, включите настройку mockReset
в конфигурации.
mockRestore
function mockRestore(): MockInstance<T>;
Выполняет те же действия, что и mockReset
, и восстанавливает внутреннюю реализацию до исходной функции.
Обратите внимание, что восстановление мока, созданного с помощью vi.fn()
, установит реализацию в пустую функцию, которая возвращает undefined
. Восстановление мока, созданного с помощью vi.fn(impl)
, восстановит реализацию до impl
.
Чтобы автоматически вызывать этот метод перед каждым тестом, включите настройку restoreMocks
в конфигурации.
mockResolvedValue
function mockResolvedValue(value: Awaited<ReturnType<T>>): MockInstance<T>;
Принимает значение, которое будет разрешено при вызове асинхронной функции. TypeScript будет принимать только значения, соответствующие типу возвращаемого значения исходной функции.
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): MockInstance<T>;
Принимает значение, которое будет разрешено при следующем вызове функции. TypeScript будет принимать только значения, соответствующие типу возвращаемого значения исходной функции. Если объединить в цепочку, каждый последующий вызов будет разрешать указанное значение.
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
function mockReturnThis(): MockInstance<T>;
Используйте это, если вам нужно вернуть контекст this
из метода, не вызывая фактическую реализацию. Это сокращение для:
spy.mockImplementation(function () {
return this;
});
mockReturnValue
function mockReturnValue(value: ReturnType<T>): MockInstance<T>;
Принимает значение, которое будет возвращаться при каждом вызове мок-функции. TypeScript будет принимать только значения, соответствующие типу возвращаемого значения исходной функции.
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
function mockReturnValueOnce(value: ReturnType<T>): MockInstance<T>;
Принимает значение, которое будет возвращаться при каждом вызове мок-функции. TypeScript будет принимать только значения, соответствующие типу возвращаемого значения исходной функции.
Когда у мок-функции заканчиваются реализации, она вызовет реализацию по умолчанию, установленную с помощью vi.fn(() => defaultValue)
или .mockImplementation(() => defaultValue)
, если они были вызваны.
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
const calls: Parameters<T>[];
Это массив, содержащий все аргументы для каждого вызова. Один элемент массива — это аргументы этого вызова.
const fn = vi.fn();
fn('arg1', 'arg2');
fn('arg3');
fn.mock.calls ===
[
['arg1', 'arg2'], // first call
['arg3'], // second call
];
mock.lastCall
const lastCall: Parameters<T> | undefined;
Содержит аргументы последнего вызова. Если мок не был вызван, он вернет undefined
.
mock.results
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>>[];
Это массив, содержащий все значения, которые были возвращены
из функции. Один элемент массива — это объект со свойствами type
и value
. Доступные типы:
'return'
- функция завершилась без выброса исключения.'throw'
- функция выбросила значение.
Свойство value
содержит возвращенное значение или выброшенную ошибку. Если функция вернула Promise
, то result
всегда будет 'return'
, даже если промис был отклонен.
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
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>>>[];
Массив, содержащий все значения, которые были разрешены
или отклонены
из функции.
Этот массив будет пустым, если функция не возвращала промис или промис еще не завершился.
const fn = vi.fn().mockResolvedValueOnce('result');
const result = fn();
fn.mock.settledResults === [];
await result;
fn.mock.settledResults ===
[
{
type: 'fulfilled',
value: 'result',
},
];
mock.invocationCallOrder
const invocationCallOrder: number[];
Это свойство возвращает порядок выполнения мок-функции. Это массив чисел, которые используются совместно всеми определенными моками.
const fn1 = vi.fn();
const fn2 = vi.fn();
fn1();
fn2();
fn1();
fn1.mock.invocationCallOrder === [1, 3];
fn2.mock.invocationCallOrder === [2];
mock.contexts
const contexts: ThisParameterType<T>[];
Массив значений this
, использованных при каждом вызове мок-функции.
const fn = vi.fn();
const context = {};
fn.apply(context);
fn.call(context);
fn.mock.contexts[0] === context;
fn.mock.contexts[1] === context;
mock.instances
const instances: ReturnType<T>[];
Содержит все экземпляры, которые были созданы при вызове мока с ключевым словом new
. Обратите внимание, что это фактический контекст (this
) функции, а не возвращаемое значение.
WARNING
Если мок был создан с помощью 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;