Fonctions Mock
Vous pouvez créer une fonction simulée pour suivre ses appels à l'aide de la méthode vi.fn
. Si vous souhaitez espionner une méthode sur un objet existant, utilisez la méthode vi.spyOn
:
import { vi } from 'vitest';
const fn = vi.fn(); // Crée une fonction simulée
fn('hello world'); // Appelle la fonction simulée
fn.mock.calls[0] === ['hello world']; // Vérifie les arguments du premier appel
const market = {
getApples: () => 100,
};
const getApplesSpy = vi.spyOn(market, 'getApples'); // Crée un espion sur la méthode getApples de l'objet market
market.getApples(); // Appelle la méthode getApples
getApplesSpy.mock.calls.length === 1; // Vérifie que l'espion a été appelé une fois
Pour vérifier le comportement d'un mock, vous devez utiliser les assertions spécifiques aux mocks (par exemple, toHaveBeenCalled
) sur l'objet expect
. Cette référence d'API décrit les propriétés et méthodes disponibles pour manipuler le comportement des mocks.
TIP
L'implémentation de fonction personnalisée dans les types ci-dessous est indiquée par un générique <T>
.
getMockImplementation
function getMockImplementation(): T | undefined;
Retourne l'implémentation actuelle du mock, si elle existe.
Si le mock a été créé avec vi.fn
, il utilisera la fonction fournie comme implémentation.
Si le mock a été créé avec vi.spyOn
, il retournera undefined
à moins qu'une implémentation personnalisée n'ait été fournie.
getMockName
function getMockName(): string;
Retourne le nom attribué au mock à l'aide de la méthode .mockName(name)
. Par défaut, il retourne vi.fn()
.
mockClear
function mockClear(): MockInstance<T>;
Efface toutes les informations relatives aux appels. Après l'avoir appelée, toutes les propriétés de .mock
retrouveront leur état initial. Cette méthode ne réinitialise pas les implémentations. Elle est utile pour purger les informations des mocks entre différentes assertions.
Pour appeler automatiquement cette méthode avant chaque test, activez le paramètre clearMocks
dans la configuration.
mockName
function mockName(name: string): MockInstance<T>;
Définit le nom interne du mock. Ceci est utile pour identifier le mock en cas d'échec d'une assertion.
mockImplementation
function mockImplementation(fn: T): MockInstance<T>;
Accepte une fonction à utiliser comme implémentation du mock. TypeScript s'attend à ce que les arguments et le type de retour correspondent à ceux de la fonction d'origine.
const mockFn = vi.fn().mockImplementation((apples: number) => apples + 1);
// ou : 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>;
Accepte une fonction à utiliser comme implémentation du mock. TypeScript s'attend à ce que les arguments et le type de retour correspondent à ceux de la fonction d'origine. Cette méthode peut être chaînée pour produire des résultats différents lors d'appels successifs.
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true) // 1er appel
.mockImplementationOnce(() => false); // 2ème appel
myMockFn(); // 1er appel : true
myMockFn(); // 2ème appel : false
Lorsque la fonction mockée n'a plus d'implémentations spécifiques (définies par 'once'), elle invoquera l'implémentation par défaut définie avec vi.fn(() => defaultValue)
ou .mockImplementation(() => defaultValue)
si celles-ci ont été spécifiées :
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>>;
Remplace temporairement l'implémentation originale du mock pendant l'exécution du callback.
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
Peut être utilisé avec un callback asynchrone. La méthode doit être attendue pour que l'implémentation originale soit restaurée par la suite.
test('async callback', async () => {
const myMockFn = vi.fn(() => 'original');
// Nous devons attendre cet appel car le callback est asynchrone
await myMockFn.withImplementation(
() => 'temp',
async () => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
});
Notez que cette méthode prend la priorité sur mockImplementationOnce
.
mockRejectedValue
function mockRejectedValue(value: unknown): MockInstance<T>;
Accepte une valeur qui sera rejetée lorsque la fonction asynchrone est appelée.
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // lance Error<'Async error'>
mockRejectedValueOnce
function mockRejectedValueOnce(value: unknown): MockInstance<T>;
Accepte une valeur qui sera rejetée lors du prochain appel de fonction. Si chaîné, chaque appel consécutif rejettera la valeur spécifiée.
const asyncMock = vi
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error'));
await asyncMock(); // 'first call'
await asyncMock(); // lance Error<'Async error'>
mockReset
function mockReset(): MockInstance<T>;
Effectue les mêmes actions que mockClear
et définit l'implémentation interne sur une fonction vide (retournant undefined
lorsqu'elle est appelée). Cela réinitialise également toutes les implémentations "once". Il est utile pour réinitialiser complètement un mock à son état par défaut.
Pour appeler automatiquement cette méthode avant chaque test, activez le paramètre mockReset
dans la configuration.
mockRestore
function mockRestore(): MockInstance<T>;
Effectue les mêmes actions que mockReset
et restaure l'implémentation interne à la fonction d'origine.
Notez que la restauration d'un mock créé avec vi.fn()
définira l'implémentation sur une fonction vide qui retourne undefined
. La restauration d'un mock créé avec vi.fn(impl)
restaurera l'implémentation à impl
.
Pour appeler automatiquement cette méthode avant chaque test, activez le paramètre restoreMocks
dans la configuration.
mockResolvedValue
function mockResolvedValue(value: Awaited<ReturnType<T>>): MockInstance<T>;
Accepte une valeur qui sera résolue lorsque la fonction asynchrone est appelée. TypeScript n'acceptera que les valeurs qui correspondent au type de retour de la fonction d'origine.
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): MockInstance<T>;
Accepte une valeur qui sera résolue lors du prochain appel de fonction. TypeScript n'acceptera que les valeurs qui correspondent au type de retour de la fonction d'origine. Si chaîné, chaque appel consécutif résoudra la valeur spécifiée.
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>;
Utilisez ceci si vous avez besoin de retourner le contexte this
de la méthode sans invoquer l'implémentation réelle. C'est un raccourci pour :
spy.mockImplementation(function () {
return this;
});
mockReturnValue
function mockReturnValue(value: ReturnType<T>): MockInstance<T>;
Accepte une valeur qui sera retournée chaque fois que la fonction mock est appelée. TypeScript n'acceptera que les valeurs qui correspondent au type de retour de la fonction d'origine.
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
function mockReturnValueOnce(value: ReturnType<T>): MockInstance<T>;
Accepte une valeur qui sera retournée lors du prochain appel de fonction. TypeScript n'acceptera que les valeurs qui correspondent au type de retour de la fonction d'origine.
Lorsque la fonction mockée n'a plus d'implémentations spécifiques (définies par 'once'), elle invoquera l'implémentation par défaut définie avec vi.fn(() => defaultValue)
ou .mockImplementation(() => defaultValue)
si celles-ci ont été spécifiées :
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>[];
C'est un tableau contenant les arguments de chaque appel. Chaque élément du tableau contient les arguments de l'appel correspondant.
const fn = vi.fn();
fn('arg1', 'arg2');
fn('arg3');
fn.mock.calls ===
[
['arg1', 'arg2'], // premier appel
['arg3'], // deuxième appel
];
mock.lastCall
const lastCall: Parameters<T> | undefined;
Ceci contient les arguments du dernier appel. Si le mock n'a pas été appelé, il retournera undefined
.
mock.results
interface MockResultReturn<T> {
type: 'return';
/**
* La valeur qui a été retournée par la fonction.
* Si la fonction a retourné une Promesse, alors ce sera une valeur résolue.
*/
value: T;
}
interface MockResultIncomplete {
type: 'incomplete';
value: undefined;
}
interface MockResultThrow {
type: 'throw';
/**
* Une erreur qui a été lancée pendant l'exécution de la fonction.
*/
value: any;
}
type MockResult<T> =
| MockResultReturn<T>
| MockResultThrow
| MockResultIncomplete;
const results: MockResult<ReturnType<T>>[];
C'est un tableau contenant les résultats de chaque appel de fonction. Chaque élément du tableau est un objet avec les propriétés type
et value
. Les types disponibles sont :
'return'
- la fonction s'est terminée normalement.'throw'
- la fonction a lancé une erreur.
La propriété value
contient la valeur retournée ou l'erreur lancée. Si la fonction a retourné une Promise
, alors la propriété type
sera toujours 'return'
même si la promesse a été rejetée.
const fn = vi
.fn()
.mockReturnValueOnce('result')
.mockImplementationOnce(() => {
throw new Error('thrown error');
});
const result = fn(); // a retourné 'result'
try {
fn(); // a levé Error
} catch {}
fn.mock.results ===
[
// premier résultat
{
type: 'return',
value: 'result',
},
// dernier résultat
{
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>>>[];
Un tableau contenant les résultats (résolus ou rejetés) de chaque appel de fonction asynchrone.
Ce tableau sera vide si la fonction n'a jamais été résolue ou rejetée.
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[];
Cette propriété retourne l'ordre d'exécution de la fonction simulée. Il s'agit d'un tableau de nombres partagés entre tous les mocks définis.
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>[];
Cette propriété est un tableau des valeurs de this
utilisées lors de chaque appel à la fonction mock.
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>[];
Cette propriété est un tableau contenant toutes les instances qui ont été créées lorsque le mock a été appelé avec le mot-clé new
. Notez qu'il s'agit du contexte réel (this
) de la fonction, et non d'une valeur de retour.
WARNING
Si le mock a été instancié avec new MyClass()
, alors mock.instances
sera un tableau avec une seule valeur :
const MyClass = vi.fn();
const a = new MyClass();
MyClass.mock.instances[0] === a;
Si vous renvoyez une valeur depuis le constructeur, elle ne sera pas dans le tableau instances
, mais plutôt dans results
:
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();
Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;