Funzioni Mock
Puoi creare una funzione mock per monitorarne l'esecuzione utilizzando il metodo vi.fn
. Se vuoi tracciare le chiamate a un metodo di un oggetto esistente, puoi usare il metodo 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;
Dovresti utilizzare le asserzioni sui mock (ad esempio, toHaveBeenCalled
) con expect
per verificare il comportamento del mock. Questo riferimento API descrive le proprietà e i metodi disponibili per manipolare il comportamento del mock.
getMockImplementation
- Tipo:
(...args: any) => any
Restituisce l'implementazione corrente del mock, se presente.
Se il mock è stato creato con vi.fn
, utilizzerà la funzione fornita come implementazione del mock.
Se il mock è stato creato con vi.spyOn
, restituirà undefined
a meno che non sia stata fornita un'implementazione personalizzata.
getMockName
- Tipo:
() => string
Utilizzalo per ottenere il nome assegnato al mock tramite il metodo .mockName(name)
.
mockClear
- Tipo:
() => MockInstance
Cancella tutte le informazioni relative a ogni chiamata. Dopo averlo chiamato, tutte le proprietà di .mock
restituiranno uno stato vuoto. Questo metodo non reimposta l'implementazione del mock. È utile se hai bisogno di pulire il mock tra diverse asserzioni.
Se vuoi che questo metodo venga chiamato automaticamente prima di ogni test, puoi abilitare l'impostazione clearMocks
nella configurazione.
mockName
- Tipo:
(name: string) => MockInstance
Imposta il nome interno del mock. Utile per identificare il mock quando un'asserzione fallisce.
mockImplementation
- Tipo:
(fn: Function) => MockInstance
Accetta una funzione da utilizzare come implementazione del mock.
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
- Tipo:
(fn: Function) => MockInstance
Accetta una funzione che verrà utilizzata come implementazione del mock durante la prossima chiamata. Può essere concatenato in modo che chiamate successive della funzione producano risultati diversi.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true)
.mockImplementationOnce(() => false);
myMockFn(); // true
myMockFn(); // false
Quando la funzione mock esaurisce le implementazioni Once
, verrà invocata l'implementazione predefinita impostata con vi.fn(() => defaultValue)
o .mockImplementation(() => defaultValue)
se sono state definite:
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
- Tipo:
(fn: Function, callback: () => void) => MockInstance
- Tipo:
(fn: Function, callback: () => Promise<unknown>) => Promise<MockInstance>
Sostituisce temporaneamente l'implementazione originale del mock durante l'esecuzione del callback.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
Può essere usato con un callback asincrono. È necessario attendere questo metodo per ripristinare l'implementazione originale.
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'
});
Nota che questo metodo ha la precedenza su mockImplementationOnce
.
mockRejectedValue
- Tipo:
(value: any) => MockInstance
Accetta un valore che verrà utilizzato per rifiutare la promise quando viene chiamata la funzione asincrona.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws "Async error"
mockRejectedValueOnce
- Tipo:
(value: any) => MockInstance
Accetta un valore che verrà utilizzato per rifiutare la promise durante la prossima chiamata di funzione. Se concatenato, ogni chiamata consecutiva rifiuterà la promise con il valore specificato.
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
- Tipo:
() => MockInstance
Esegue la stessa operazione di mockClear
e trasforma l'implementazione interna in una funzione vuota (restituendo undefined
quando invocata). Questo reimposta anche tutte le implementazioni "once". Questo è utile quando vuoi reimpostare completamente un mock allo stato predefinito.
Se vuoi che questo metodo venga chiamato automaticamente prima di ogni test, puoi abilitare l'impostazione mockReset
nella configurazione.
mockRestore
- Tipo:
() => MockInstance
Esegue la stessa operazione di mockReset
e ripristina l'implementazione interna alla funzione originale.
Nota che ripristinando un mock creato con vi.fn()
imposterà l'implementazione a una funzione vuota che restituisce undefined
. Il ripristino di un vi.fn(impl)
ripristinerà l'implementazione a impl
.
Se vuoi che questo metodo venga chiamato automaticamente prima di ogni test, puoi abilitare l'impostazione restoreMocks
nella configurazione.
mockResolvedValue
- Tipo:
(value: any) => MockInstance
Accetta un valore che verrà utilizzato per risolvere la promise quando viene chiamata la funzione asincrona.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
- Tipo:
(value: any) => MockInstance
Accetta un valore che verrà utilizzato per risolvere la promise durante la prossima chiamata di funzione. Se concatenato, ogni chiamata consecutiva risolverà la promise con il valore specificato.
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
- Tipo:
() => MockInstance
Utilizza questo metodo se devi restituire il contesto this
dal metodo senza invocare l'implementazione effettiva. Questo è un modo abbreviato per:
spy.mockImplementation(function () {
return this;
});
mockReturnValue
- Tipo:
(value: any) => MockInstance
Accetta un valore che verrà restituito ogni volta che viene chiamata la funzione mock.
import { vi } from 'vitest';
// ---cut---
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
- Tipo:
(value: any) => MockInstance
Accetta un valore che verrà restituito durante la prossima chiamata di funzione. Se concatenato, ogni chiamata consecutiva restituirà il valore specificato.
Quando non ci sono più valori mockReturnValueOnce
da usare, il mock ritornerà all'implementazione precedentemente definita, se presente.
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
Questo array contiene tutti gli argomenti passati a ogni chiamata. Un elemento dell'array rappresenta gli argomenti di quella specifica chiamata.
const fn = vi.fn();
fn('arg1', 'arg2');
fn('arg3');
fn.mock.calls ===
[
['arg1', 'arg2'], // first call
['arg3'], // second call
];
mock.lastCall
Contiene gli argomenti dell'ultima chiamata. Se il mock non è stato chiamato, restituirà undefined
.
mock.results
Questo array contiene tutti i valori restituiti
dalla funzione. Un elemento dell'array è un oggetto con le proprietà type
e value
. I tipi disponibili sono:
'return'
- la funzione è stata eseguita senza generare un'eccezione.'throw'
- la funzione ha lanciato un'eccezione.
La proprietà value
contiene il valore restituito o l'errore lanciato. Se la funzione ha restituito una promise, il value
sarà il valore risolto, non la Promise
effettiva, a meno che non sia mai stata risolta.
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
L'ordine in cui il mock è stato eseguito. Restituisce un array di numeri condivisi tra tutti i mock definiti.
const fn1 = vi.fn();
const fn2 = vi.fn();
fn1();
fn2();
fn1();
fn1.mock.invocationCallOrder === [1, 3];
fn2.mock.invocationCallOrder === [2];
mock.instances
Si noti che questo rappresenta il contesto effettivo (this
) della funzione, non un valore di ritorno.
WARNING
Se il mock è stato istanziato con new MyClass()
, allora mock.instances
sarà un array con un valore:
const MyClass = vi.fn();
const a = new MyClass();
MyClass.mock.instances[0] === a;
Se si restituisce un valore dal costruttore, questo non sarà presente nell'array instances
, ma all'interno di results
:
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();
Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;