Funkcje Mock
Możesz utworzyć mock, aby śledzić jego wykonanie za pomocą metody vi.fn
. Aby śledzić metodę na już istniejącym obiekcie, użyj metody 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;
Używaj asercji mock (np. toHaveBeenCalled
) na expect
, aby potwierdzić wynik. To odniesienie do API opisuje dostępne właściwości i metody do manipulacji zachowaniem mocków.
TIP
Niestandardowa implementacja funkcji w poniższych typach jest oznaczona jako generyczny <T>
.
getMockImplementation
function getMockImplementation(): T | undefined;
Zwraca bieżącą implementację mocka, jeśli taka istnieje.
Jeśli mock został utworzony za pomocą vi.fn
, użyje podanej metody jako implementacji mocka.
Jeśli mock został utworzony za pomocą vi.spyOn
, zwróci undefined
, chyba że zostanie podana niestandardowa implementacja.
getMockName
function getMockName(): string;
Użyj tej metody, aby zwrócić nazwę przypisaną do mocka za pomocą metody .mockName(name)
. Domyślnie zwróci wartość vi.fn()
.
mockClear
function mockClear(): MockInstance<T>;
Usuwa wszystkie informacje o każdym wywołaniu. Po wywołaniu wszystkie właściwości na .mock
powrócą do stanu początkowego. Ta metoda nie resetuje implementacji. Jest przydatna do czyszczenia mocków między różnymi asercjami.
Aby automatycznie wywoływać tę metodę przed każdym testem, włącz ustawienie clearMocks
w konfiguracji.
mockName
function mockName(name: string): MockInstance<T>;
Ustawia wewnętrzną nazwę mocka. Jest to przydatne do identyfikacji mocka, gdy asercja zakończy się niepowodzeniem.
mockImplementation
function mockImplementation(fn: T): MockInstance<T>;
Akceptuje funkcję, która ma być używana jako implementacja mocka. TypeScript oczekuje, że argumenty i typ zwracany będą zgodne z oryginalną funkcją.
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>;
Akceptuje funkcję, która ma być używana jako implementacja mocka. TypeScript oczekuje, że argumenty i typ zwracany będą zgodne z oryginalną funkcją. Tę metodę można łączyć w łańcuch, aby uzyskać różne wyniki dla wielu wywołań funkcji.
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true) // 1st call
.mockImplementationOnce(() => false); // 2nd call
myMockFn(); // 1st call: true
myMockFn(); // 2nd call: false
Gdy mockowana funkcja wyczerpie implementacje, wywoła domyślną implementację ustawioną za pomocą vi.fn(() => defaultValue)
lub .mockImplementation(() => defaultValue)
, jeśli zostały wywołane:
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>>;
Tymczasowo zastępuje oryginalną implementację mocka podczas wykonywania funkcji zwrotnej.
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
Może być używana z asynchroniczną funkcją zwrotną. Metodę należy wywołać z await
, aby później użyć oryginalnej implementacji.
test('async callback', async () => {
const myMockFn = vi.fn(() => 'original');
// We await this call since the callback is async
await myMockFn.withImplementation(
() => 'temp',
async () => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
});
Należy pamiętać, że ta metoda ma pierwszeństwo przed mockImplementationOnce
.
mockRejectedValue
function mockRejectedValue(value: unknown): MockInstance<T>;
Przyjmuje błąd, który zostanie odrzucony po wywołaniu funkcji asynchronicznej.
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws Error<'Async error'>
mockRejectedValueOnce
function mockRejectedValueOnce(value: unknown): MockInstance<T>;
Akceptuje wartość, która zostanie odrzucona podczas następnego wywołania funkcji. Jeśli połączone w łańcuch, każde kolejne wywołanie odrzuci określoną wartość.
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>;
Wykonuje te same czynności co mockClear
i ustawia wewnętrzną implementację na pustą funkcję (zwracającą wartość undefined
po wywołaniu). Resetuje również wszystkie implementacje "once". Jest przydatna do całkowitego zresetowania mocka do stanu domyślnego.
Aby automatycznie wywoływać tę metodę przed każdym testem, włącz ustawienie mockReset
w konfiguracji.
mockRestore
function mockRestore(): MockInstance<T>;
Wykonuje te same czynności co mockReset
i przywraca wewnętrzną implementację do oryginalnej funkcji.
Zauważ, że przywrócenie mocka utworzonego za pomocą vi.fn()
ustawi implementację na pustą funkcję, która zwraca undefined
. Przywrócenie mocka utworzonego za pomocą vi.fn(impl)
przywróci implementację do impl
.
Aby automatycznie wywoływać tę metodę przed każdym testem, włącz ustawienie restoreMocks
w konfiguracji.
mockResolvedValue
function mockResolvedValue(value: Awaited<ReturnType<T>>): MockInstance<T>;
Akceptuje wartość, która zostanie rozwiązana po wywołaniu funkcji asynchronicznej. TypeScript zaakceptuje tylko wartości zgodne z typem zwracanym przez oryginalną funkcję.
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): MockInstance<T>;
Akceptuje wartość, która zostanie rozwiązana podczas następnego wywołania funkcji. TypeScript zaakceptuje tylko wartości zgodne z typem zwracanym przez oryginalną funkcję. Jeśli połączone w łańcuch, każde kolejne wywołanie rozwiąże określoną wartość.
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>;
Użyj tej metody, jeśli musisz zwrócić kontekst this
z metody bez wywoływania rzeczywistej implementacji. Jest to skrót dla:
spy.mockImplementation(function () {
return this;
});
mockReturnValue
function mockReturnValue(value: ReturnType<T>): MockInstance<T>;
Akceptuje wartość, która zostanie zwrócona za każdym razem, gdy funkcja mocka zostanie wywołana. TypeScript zaakceptuje tylko wartości zgodne z typem zwracanym przez oryginalną funkcję.
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
function mockReturnValueOnce(value: ReturnType<T>): MockInstance<T>;
Akceptuje wartość, która zostanie zwrócona za każdym razem, gdy funkcja mocka zostanie wywołana. TypeScript zaakceptuje tylko wartości zgodne z typem zwracanym przez oryginalną funkcję.
Gdy zamockowana funkcja wyczerpie implementacje, wywoła domyślną implementację ustawioną za pomocą vi.fn(() => defaultValue)
lub .mockImplementation(() => defaultValue)
, jeśli zostały wywołane:
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>[];
To tablica zawierająca wszystkie argumenty dla każdego wywołania. Jeden element tablicy to argumenty tego wywołania.
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;
Przechowuje argumenty ostatniego wywołania. Jeśli mock nie został wywołany, zwróci 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>>[];
Jest to tablica zawierająca wszystkie wartości, które zostały zwrócone
z funkcji. Jeden element tablicy to obiekt z właściwościami type
i value
. Dostępne typy to:
'return'
- funkcja zwróciła wartość bez rzucania wyjątku.'throw'
- funkcja rzuciła wyjątkiem.
Właściwość value
zawiera zwróconą wartość lub rzucony błąd. Jeśli funkcja zwróciła Promise
, result
zawsze będzie 'return'
, nawet jeśli obietnica została odrzucona.
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>>>[];
Tablica zawierająca wszystkie wartości, które zostały rozwiązane
lub odrzucone
z funkcji.
Ta tablica będzie pusta, jeśli funkcja nigdy nie została rozwiązana ani odrzucona.
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[];
Ta właściwość przechowuje kolejność wykonania funkcji mocka. Jest to tablica liczb, które są wspólne dla wszystkich zdefiniowanych mocków.
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>[];
Ta właściwość to tablica wartości this
używanych podczas każdego wywołania funkcji mocka.
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>[];
Ta właściwość to tablica zawierająca wszystkie instancje, które zostały utworzone, gdy mock został wywołany ze słowem kluczowym new
. Zauważ, że jest to rzeczywisty kontekst (this
) funkcji, a nie wartość zwracana.
WARNING
Jeśli mock został zainicjowany za pomocą new MyClass()
, to mock.instances
będzie tablicą z jedną wartością:
const MyClass = vi.fn();
const a = new MyClass();
MyClass.mock.instances[0] === a;
Jeśli zwrócisz wartość z konstruktora, nie będzie ona w tablicy instances
, ale zamiast tego w results
:
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();
Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;