Mockovací funkce
Můžete vytvořit mockovací funkci pro sledování jejího provedení pomocí metody vi.fn
. Pokud chcete sledovat metodu existujícího objektu, můžete použít metodu 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;
Pro ověření výsledku mocku byste měli použít aserce mocku (např. toHaveBeenCalled
) na expect
. Tato API reference popisuje dostupné vlastnosti a metody pro úpravu chování mocku.
TIP
Uživatelská implementace funkce v níže uvedených typech je označena generickým <T>
.
getMockImplementation
function getMockImplementation(): T | undefined;
Vrátí aktuální implementaci mocku, pokud nějaká existuje.
Pokud byl mock vytvořen pomocí vi.fn
, použije zadanou metodu jako implementaci mocku.
Pokud byl mock vytvořen pomocí vi.spyOn
, vrátí undefined
, pokud není dodána vlastní implementace.
getMockName
function getMockName(): string;
Tuto metodu použijte k vrácení názvu, který byl přiřazen mocku metodou .mockName(name)
. Ve výchozím nastavení vrátí vi.fn()
.
mockClear
function mockClear(): MockInstance<T>;
Vymaže všechny informace o všech voláních. Po jejím zavolání se všechny vlastnosti na .mock
vrátí do svého počátečního stavu. Tato metoda neobnovuje implementace. Je užitečná pro vyčištění mocků mezi jednotlivými tvrzeními.
const person = {
greet: (name: string) => `Hello ${name}`,
};
const spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked');
expect(person.greet('Alice')).toBe('mocked');
expect(spy.mock.calls).toEqual([['Alice']]);
// vymaže historii volání, ale zachová implementaci mocku
spy.mockClear();
expect(spy.mock.calls).toEqual([]);
expect(person.greet('Bob')).toBe('mocked');
expect(spy.mock.calls).toEqual([['Bob']]);
Pro automatické volání této metody před každým testem aktivujte nastavení clearMocks
v konfiguraci.
mockName
function mockName(name: string): MockInstance<T>;
Nastaví interní název mocku. To je užitečné pro identifikaci mocku při selhání aserce.
mockImplementation
function mockImplementation(fn: T): MockInstance<T>;
Přijímá funkci, která bude použita jako implementace mocku. TypeScript očekává, že argumenty a návratový typ se shodují s těmi u původní funkce.
const mockFn = vi.fn().mockImplementation((apples: number) => apples + 1);
// nebo: 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>;
Přijímá funkci, která má být použita jako implementace mocku. TypeScript očekává, že argumenty a návratový typ se shodují s těmi u původní funkce. Tuto metodu lze řetězit, aby se dosáhlo různých výsledků pro vícenásobná volání funkce.
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true) // 1. volání
.mockImplementationOnce(() => false); // 2. volání
myMockFn(); // 1. volání: true
myMockFn(); // 2. volání: false
Když mockovaná funkce vyčerpá své implementace, vyvolá výchozí implementaci nastavenou pomocí vi.fn(() => defaultValue)
nebo .mockImplementation(() => defaultValue)
, pokud byly volány:
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>>;
Dočasně přepíše původní implementaci mocku po dobu provádění callbacku.
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
Lze použít s asynchronním callbackem. Na metodu je třeba počkat (await), aby se poté použila původní implementace.
test('async callback', async () => {
const myMockFn = vi.fn(() => 'original');
// Toto volání awaitujeme, protože callback je asynchronní
await myMockFn.withImplementation(
() => 'temp',
async () => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
});
Všimněte si, že tato metoda má přednost před mockImplementationOnce
.
mockRejectedValue
function mockRejectedValue(value: unknown): MockInstance<T>;
Přijímá chybu, která bude zamítnuta, když je volána asynchronní funkce.
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // vyhodí Error<'Async error'>
mockRejectedValueOnce
function mockRejectedValueOnce(value: unknown): MockInstance<T>;
Přijímá hodnotu, která bude zamítnuta během dalšího volání funkce. Pokud je zřetězena, každé následující volání zamítne specifikovanou hodnotu.
const asyncMock = vi
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error'));
await asyncMock(); // 'first call'
await asyncMock(); // vyhodí Error<'Async error'>
mockReset
function mockReset(): MockInstance<T>;
Provádí stejnou funkci jako mockClear
a navíc resetuje vnitřní implementaci na původní funkci. Tím se také resetují všechny jednorázové implementace.
Všimněte si, že resetování mocku z vi.fn()
nastaví implementaci na prázdnou funkci, která vrací undefined
. Resetování mocku z vi.fn(impl)
obnoví implementaci na impl
.
To je užitečné, když chcete mock vrátit do jeho původního stavu.
const person = {
greet: (name: string) => `Hello ${name}`,
};
const spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked');
expect(person.greet('Alice')).toBe('mocked');
expect(spy.mock.calls).toEqual([['Alice']]);
// vymaže historii volání a resetuje implementaci, ale metoda je stále sledována
spy.mockReset();
expect(spy.mock.calls).toEqual([]);
expect(person.greet).toBe(spy);
expect(person.greet('Bob')).toBe('Hello Bob');
expect(spy.mock.calls).toEqual([['Bob']]);
Pro automatické volání této metody před každým testem povolte nastavení mockReset
v konfiguraci.
mockRestore
function mockRestore(): MockInstance<T>;
Provádí stejnou funkci jako mockReset
a navíc obnovuje původní deskriptory sledovaných objektů.
Všimněte si, že obnovení mocku z vi.fn()
nastaví implementaci na prázdnou funkci, která vrací undefined
. Obnovení mocku z vi.fn(impl)
obnoví implementaci na impl
.
const person = {
greet: (name: string) => `Hello ${name}`,
};
const spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked');
expect(person.greet('Alice')).toBe('mocked');
expect(spy.mock.calls).toEqual([['Alice']]);
// vymaže historii volání a obnoví sledovanou metodu objektu
spy.mockRestore();
expect(spy.mock.calls).toEqual([]);
expect(person.greet).not.toBe(spy);
expect(person.greet('Bob')).toBe('Hello Bob');
expect(spy.mock.calls).toEqual([]);
Pro automatické volání této metody před každým testem povolte nastavení restoreMocks
v konfiguraci.
mockResolvedValue
function mockResolvedValue(value: Awaited<ReturnType<T>>): MockInstance<T>;
Přijímá hodnotu, která bude vyřešena, když je volána asynchronní funkce. TypeScript přijme pouze hodnoty, které odpovídají návratovému typu původní funkce.
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): MockInstance<T>;
Přijímá hodnotu, která bude vyřešena během dalšího volání funkce. TypeScript přijme pouze hodnoty, které odpovídají návratovému typu původní funkce. Pokud je zřetězena, každé následující volání vyřeší specifikovanou hodnotu.
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>;
Použijte tuto metodu, pokud potřebujete vrátit kontext this
z metody, aniž by se vyvolala skutečná implementace. Jedná se o zkratku pro:
spy.mockImplementation(function () {
return this;
});
mockReturnValue
function mockReturnValue(value: ReturnType<T>): MockInstance<T>;
Přijímá hodnotu, která bude vrácena vždy, když je volána mock funkce. TypeScript přijme pouze hodnoty, které odpovídají návratovému typu původní funkce.
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
function mockReturnValueOnce(value: ReturnType<T>): MockInstance<T>;
Přijímá hodnotu, která bude vrácena vždy, když je volána mock funkce. TypeScript přijme pouze hodnoty, které odpovídají návratovému typu původní funkce.
Když mockované funkci dojdou implementace, vyvolá výchozí implementaci nastavenou pomocí vi.fn(() => defaultValue)
nebo .mockImplementation(() => defaultValue)
, pokud byly volány:
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>[];
Toto je pole obsahující všechny argumenty pro každé volání. Každá položka pole představuje argumenty daného volání.
const fn = vi.fn();
fn('arg1', 'arg2');
fn('arg3');
fn.mock.calls ===
[
['arg1', 'arg2'], // první volání
['arg3'], // druhé volání
];
mock.lastCall
const lastCall: Parameters<T> | undefined;
Toto obsahuje argumenty posledního volání. Pokud mock nebyl dosud volán, vrátí undefined
.
mock.results
interface MockResultReturn<T> {
type: 'return';
/**
* Hodnota, která byla vrácena z funkce.
* Pokud funkce vrátila Promise, pak to bude vyřešená hodnota.
*/
value: T;
}
interface MockResultIncomplete {
type: 'incomplete';
value: undefined;
}
interface MockResultThrow {
type: 'throw';
/**
* Chyba, která byla vyhozena během provádění funkce.
*/
value: any;
}
type MockResult<T> =
| MockResultReturn<T>
| MockResultThrow
| MockResultIncomplete;
const results: MockResult<ReturnType<T>>[];
Toto je pole obsahující všechny hodnoty, které funkce vrátila
. Jedna položka pole je objekt s vlastnostmi type
a value
. Dostupné typy jsou:
'return'
- funkce se vrátila bez vyhození výjimky.'throw'
- funkce vyhodila výjimku.
Vlastnost value
obsahuje vrácenou hodnotu nebo vyhozenou chybu. Pokud funkce vrátila Promise
, pak result
bude vždy 'return'
, i když byl promise zamítnut.
const fn = vi
.fn()
.mockReturnValueOnce('result')
.mockImplementationOnce(() => {
throw new Error('thrown error');
});
const result = fn(); // vráceno 'result'
try {
fn(); // vyhozena chyba
} catch {}
fn.mock.results ===
[
// první výsledek
{
type: 'return',
value: 'result',
},
// poslední výsledek
{
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>>>[];
Pole obsahující všechny hodnoty, které funkce vyřešila
nebo zamítla
.
Toto pole bude prázdné, pokud funkce nebyla nikdy vyřešena nebo zamítnuta.
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[];
Tato vlastnost vrací pořadí, ve kterém byla mock funkce spuštěna. Jedná se o pole čísel, která jsou sdílena mezi všemi definovanými mocky.
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>[];
Tato vlastnost je pole hodnot this
, které byly použity během každého volání mock funkce.
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>[];
Tato vlastnost je pole obsahující všechny instance, které byly vytvořeny, když byl mock volán pomocí klíčového slova new
. Všimněte si, že se jedná o skutečný kontext (this
) funkce, nikoli o její návratovou hodnotu.
WARNING
Pokud byl mock vytvořen pomocí new MyClass()
, pak mock.instances
bude pole s jednou hodnotou:
const MyClass = vi.fn();
const a = new MyClass();
MyClass.mock.instances[0] === a;
Pokud vrátíte hodnotu z konstruktoru, nebude se nacházet v poli instances
, ale místo toho v results
:
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();
Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;