Funkcje Mockujące
Możesz utworzyć funkcję mock, aby śledzić jej wykonanie za pomocą metody vi.fn()
. Jeśli chcesz śledzić wywołania metody istniejącego obiektu, możesz użyć 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;
Powinieneś używać asercji mock (np. toHaveBeenCalled
) w połączeniu z expect
, aby sprawdzić i zweryfikować zachowanie mocka. Ten dokument API opisuje dostępne właściwości i metody do manipulowania zachowaniem mocków.
getMockImplementation
- Typ:
(...args: any) => any
Zwraca aktualną implementację mocka, jeśli taka istnieje.
Jeśli mock został utworzony za pomocą vi.fn
, funkcja przekazana do vi.fn
zostanie uznana za implementację mockującą.
Jeśli mock został utworzony za pomocą vi.spyOn
, zwróci undefined
, chyba że dostarczono niestandardową implementację.
getMockName
- Typ:
() => string
Służy do zwracania nazwy nadanej mockowi za pomocą metody .mockName(name)
.
mockClear
- Typ:
() => MockInstance
Czyści wszystkie informacje o wywołaniach mocka. Po wywołaniu tej metody wszystkie właściwości w .mock
zwrócą pusty stan. Ta metoda nie resetuje implementacji. Jest przydatna, gdy musisz zresetować mock między różnymi asercjami.
Jeśli chcesz, aby ta metoda była wywoływana automatycznie przed każdym testem, możesz włączyć opcję clearMocks
w konfiguracji.
mockName
- Typ:
(name: string) => MockInstance
Ustawia wewnętrzną nazwę mocka. Przydatne do identyfikacji mocka, gdy asercja się nie powiedzie.
mockImplementation
- Typ:
(fn: Function) => MockInstance
Akceptuje funkcję, która będzie używana jako implementacja mocka.
import { vi } from 'vitest';
// ---cut---
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
- Typ:
(fn: Function) => MockInstance
Akceptuje funkcję, która będzie używana jako implementacja mocka podczas następnego wywołania. Można ją wywoływać wielokrotnie, aby kolejne wywołania funkcji dawały różne wyniki.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true)
.mockImplementationOnce(() => false);
myMockFn(); // true
myMockFn(); // false
Gdy funkcja mock nie ma więcej zdefiniowanych implementacji Once
, wywoła domyślną implementację ustawioną za pomocą vi.fn(() => defaultValue)
lub .mockImplementation(() => defaultValue)
, jeśli zostały one wcześniej wywołane:
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
- Typ:
(fn: Function, callback: () => void) => MockInstance
- Typ:
(fn: Function, callback: () => Promise<unknown>) => Promise<MockInstance>
Tymczasowo zastępuje oryginalną implementację mocka podczas wykonywania funkcji zwrotnej (callback).
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
Może być używana z asynchroniczną funkcją zwrotną. Należy poczekać na zakończenie tej metody (używając await
), aby przywrócić oryginalną implementację po zakończeniu callbacka.
test('async callback', () => {
const myMockFn = vi.fn(() => 'original');
// Oczekujemy (await) na to wywołanie, ponieważ callback jest asynchroniczny
await myMockFn.withImplementation(
() => 'temp',
async () => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
});
Zauważ, że ta metoda ma pierwszeństwo przed mockImplementationOnce
.
mockRejectedValue
- Typ:
(value: any) => MockInstance
Akceptuje wartość, która zostanie zwrócona jako odrzucona Promise, gdy zostanie wywołana funkcja asynchroniczna.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws "Async error"
mockRejectedValueOnce
- Typ:
(value: any) => MockInstance
Akceptuje wartość, która zostanie zwrócona jako odrzucona Promise podczas następnego wywołania funkcji. Jeśli metoda zostanie wywołana wielokrotnie, każde kolejne wywołanie zwróci jako odrzuconą Promise określoną wartość.
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
- Typ:
() => MockInstance
Robi to, co mockClear
, a dodatkowo ustawia wewnętrzną implementację na pustą funkcję (która zwraca undefined
po wywołaniu). Dodatkowo resetuje wszystkie implementacje zdefiniowane za pomocą mockImplementationOnce
i mockReturnValueOnce
. Jest to przydatne, gdy chcesz całkowicie zresetować mock do stanu początkowego.
Jeśli chcesz, aby ta metoda była wywoływana automatycznie przed każdym testem, możesz włączyć opcję mockReset
w konfiguracji.
mockRestore
- Typ:
() => MockInstance
Robi to, co mockReset
, a dodatkowo 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
.
Jeśli chcesz, aby ta metoda była wywoływana automatycznie przed każdym testem, możesz włączyć opcję restoreMocks
w konfiguracji.
mockResolvedValue
- Typ:
(value: any) => MockInstance
Akceptuje wartość, która zostanie zwrócona jako rozwiązana Promise, gdy zostanie wywołana funkcja asynchroniczna.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
- Typ:
(value: any) => MockInstance
Akceptuje wartość, która zostanie zwrócona jako rozwiązana Promise podczas następnego wywołania funkcji. Jeśli metoda zostanie wywołana wielokrotnie, każde kolejne wywołanie zwróci jako rozwiązaną Promise określoną wartość.
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
- Typ:
() => MockInstance
Użyj tego, jeśli musisz zwrócić kontekst this
z metody bez wywoływania rzeczywistej implementacji. To jest skrót dla:
spy.mockImplementation(function () {
return this;
});
mockReturnValue
- Typ:
(value: any) => MockInstance
Akceptuje wartość, która będzie zwracana za każdym razem, gdy zostanie wywołana funkcja mock.
import { vi } from 'vitest';
// ---cut---
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
- Typ:
(value: any) => MockInstance
Akceptuje wartość, która zostanie zwrócona podczas następnego wywołania funkcji. Jeśli jest połączona łańcuchowo, każde kolejne wywołanie zwróci określoną wartość.
Gdy nie ma więcej wartości mockReturnValueOnce
do użycia, mock powróci do wcześniej zdefiniowanej implementacji, jeśli taka istnieje.
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
To jest tablica zawierająca argumenty każdego wywołania funkcji mock.
const fn = vi.fn();
fn('arg1', 'arg2');
fn('arg3');
fn.mock.calls ===
[
['arg1', 'arg2'], // pierwsze wywołanie
['arg3'], // drugie wywołanie
];
mock.lastCall
Zawiera argumenty ostatniego wywołania. Jeśli mock nie został wywołany, zwróci undefined
.
mock.results
To jest tablica zawierająca informacje o wszystkich wartościach zwróconych przez funkcję. 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ątek.
Właściwość value
zawiera zwróconą wartość lub rzucony błąd. Jeśli funkcja zwróciła obietnicę, value
będzie rozwiązaną wartością, a nie rzeczywistą Promise
, chyba że nigdy nie została rozwiązana.
const fn = vi
.fn()
.mockReturnValueOnce('result')
.mockImplementationOnce(() => {
throw new Error('thrown error');
});
const result = fn(); // zwróciła 'result'
try {
fn(); // rzuciła Error
} catch {}
fn.mock.results ===
[
// pierwszy wynik
{
type: 'return',
value: 'result',
},
// ostatni wynik
{
type: 'throw',
value: Error,
},
];
mock.invocationCallOrder
Kolejność wywołań mocków. Zwraca tablicę liczb reprezentujących kolejność wywołań, współdzieloną przez wszystkie zdefiniowane mocki.
const fn1 = vi.fn();
const fn2 = vi.fn();
fn1();
fn2();
fn1();
fn1.mock.invocationCallOrder === [1, 3];
fn2.mock.invocationCallOrder === [2];
mock.instances
To jest tablica zawierająca wszystkie instancje utworzone za pomocą słowa kluczowego new
podczas wywoływania mocka. Zauważ, że to jest rzeczywisty kontekst (this
) funkcji, a nie wartość zwracana.
WARNING
Jeśli mock został utworzony 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 wewnątrz results
:
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();
Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;