Aller au contenu principal
Version : 29.7

Fonctions Mock

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

Les fonctions mock sont aussi appelées "spies" (espions) car elles permettent d'observer le comportement d'une fonction appelée indirectement par du code tiers, au-delà du simple test du résultat. Vous pouvez créer une fonction mock avec jest.fn(). Si aucune implémentation n'est fournie, la fonction mock renverra undefined lorsqu'elle est appelée.

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

info

Les exemples TypeScript de cette page ne fonctionneront comme documenté que si vous importez explicitement les API Jest :

import {expect, jest, test} from '@jest/globals';

Consultez le guide Premiers pas pour plus de détails sur la configuration de Jest avec TypeScript.

Méthodes


Référence

mockFn.getMockName()

Renvoie le nom de mock défini en appelant .mockName().

mockFn.mock.calls

Un tableau contenant les arguments d'appel de tous les appels passés à cette fonction mock. Chaque élément du tableau est un tableau d'arguments passés lors de l'appel.

Par exemple : une fonction mock f appelée deux fois avec les arguments f('arg1', 'arg2') puis f('arg3', 'arg4') aura un tableau mock.calls ressemblant à ceci :

[
['arg1', 'arg2'],
['arg3', 'arg4'],
];

mockFn.mock.results

Un tableau contenant les résultats de tous les appels passés à cette fonction mock. Chaque entrée est un objet contenant une propriété type et une propriété value. type peut prendre l'une des valeurs suivantes :

  • 'return' - Indique que l'appel s'est terminé par un retour normal.

  • 'throw' - Indique que l'appel s'est terminé par une erreur levée.

  • 'incomplete' - Indique que l'appel n'est pas encore terminé. Cela se produit si vous testez le résultat depuis la fonction mock elle-même ou depuis une fonction appelée par le mock.

La propriété value contient la valeur renvoyée ou l'erreur levée. value est undefined quand type === 'incomplete'.

Par exemple : une fonction mock f appelée trois fois, renvoyant 'result1', levant une erreur, puis renvoyant 'result2', aura un tableau mock.results ressemblant à ceci :

[
{
type: 'return',
value: 'result1',
},
{
type: 'throw',
value: {
/* Error instance */
},
},
{
type: 'return',
value: 'result2',
},
];

mockFn.mock.instances

Un tableau contenant toutes les instances d'objets instanciées à partir de cette fonction mock via new.

Par exemple : une fonction mock instanciée deux fois aura le tableau mock.instances suivant :

const mockFn = jest.fn();

const a = new mockFn();
const b = new mockFn();

mockFn.mock.instances[0] === a; // true
mockFn.mock.instances[1] === b; // true

mockFn.mock.contexts

Un tableau contenant les contextes de tous les appels de la fonction mock.

Un contexte est la valeur this reçue par une fonction lors de son appel. Le contexte peut être défini via Function.prototype.bind, Function.prototype.call ou Function.prototype.apply.

Par exemple :

const mockFn = jest.fn();

const boundMockFn = mockFn.bind(thisContext0);
boundMockFn('a', 'b');
mockFn.call(thisContext1, 'a', 'b');
mockFn.apply(thisContext2, ['a', 'b']);

mockFn.mock.contexts[0] === thisContext0; // true
mockFn.mock.contexts[1] === thisContext1; // true
mockFn.mock.contexts[2] === thisContext2; // true

mockFn.mock.lastCall

Un tableau contenant les arguments du dernier appel passé à cette fonction mock. Si la fonction n'a jamais été appelée, renvoie undefined.

Par exemple : une fonction mock f appelée deux fois avec les arguments f('arg1', 'arg2') puis f('arg3', 'arg4') aura un tableau mock.lastCall ressemblant à ceci :

['arg3', 'arg4'];

mockFn.mockClear()

Vide toutes les informations stockées dans les tableaux mockFn.mock.calls, mockFn.mock.instances, mockFn.mock.contexts et mockFn.mock.results. Utile pour nettoyer les données d'utilisation entre deux assertions.

L'option de configuration clearMocks permet de vider automatiquement les mocks avant chaque test.

attention

Attention : mockFn.mockClear() remplacera entièrement mockFn.mock, pas seulement réinitialisera ses valeurs ! Vous devez donc éviter d'assigner mockFn.mock à d'autres variables, temporaires ou non, pour ne pas accéder à des données obsolètes.

mockFn.mockReset()

Fait tout ce que mockFn.mockClear() fait, et remplace également l'implémentation fictive par une fonction vide qui renvoie undefined.

L'option de configuration resetMocks permet de réinitialiser automatiquement les mocks avant chaque test.

mockFn.mockRestore()

Fait tout ce que mockFn.mockReset() fait, et restaure également l'implémentation originale (non simulée).

Utile quand vous voulez simuler des fonctions dans certains cas de test et restaurer l'implémentation originale dans d'autres.

L'option de configuration restoreMocks permet de restaurer automatiquement les mocks avant chaque test.

info

mockFn.mockRestore() ne fonctionne que si le mock a été créé avec jest.spyOn(). Vous devez donc gérer manuellement la restauration quand vous assignez jest.fn() directement.

mockFn.mockImplementation(fn)

Accepte une fonction à utiliser comme implémentation du mock. Le mock continuera d'enregistrer tous les appels entrants et les instances créées – la seule différence est que l'implémentation sera exécutée lors de l'appel.

astuce

jest.fn(implementation) est un raccourci pour jest.fn().mockImplementation(implementation).

const mockFn = jest.fn(scalar => 42 + scalar);

mockFn(0); // 42
mockFn(1); // 43

mockFn.mockImplementation(scalar => 36 + scalar);

mockFn(2); // 38
mockFn(3); // 39

.mockImplementation() peut aussi simuler des constructeurs de classe :

SomeClass.js
module.exports = class SomeClass {
method(a, b) {}
};
SomeClass.test.js
const SomeClass = require('./SomeClass');

jest.mock('./SomeClass'); // this happens automatically with automocking

const mockMethod = jest.fn();
SomeClass.mockImplementation(() => {
return {
method: mockMethod,
};
});

const some = new SomeClass();
some.method('a', 'b');

console.log('Calls to method:', mockMethod.mock.calls);

mockFn.mockImplementationOnce(fn)

Accepte une fonction utilisée comme implémentation du mock pour un seul appel. Peut être chaînée pour produire différents résultats sur plusieurs appels.

const mockFn = jest
.fn()
.mockImplementationOnce(cb => cb(null, true))
.mockImplementationOnce(cb => cb(null, false));

mockFn((err, val) => console.log(val)); // true
mockFn((err, val) => console.log(val)); // false

Quand le mock épuise les implémentations définies par .mockImplementationOnce(), il exécute l'implémentation par défaut définie avec jest.fn(() => defaultValue) ou .mockImplementation(() => defaultValue) si elles ont été appelées :

const mockFn = jest
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');

mockFn(); // 'first call'
mockFn(); // 'second call'
mockFn(); // 'default'
mockFn(); // 'default'

mockFn.mockName(name)

Accepte une chaîne à utiliser dans les résultats de test à la place de 'jest.fn()' pour identifier la fonction mockée.

Par exemple :

const mockFn = jest.fn().mockName('mockedFunction');

// mockFn();
expect(mockFn).toHaveBeenCalled();

Produira cette erreur :

expect(mockedFunction).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls: 0

mockFn.mockReturnThis()

Raccourci pour :

jest.fn(function () {
return this;
});

mockFn.mockReturnValue(value)

Raccourci pour :

jest.fn().mockImplementation(() => value);

Accepte une valeur qui sera retournée à chaque appel de la fonction mockée.

const mock = jest.fn();

mock.mockReturnValue(42);
mock(); // 42

mock.mockReturnValue(43);
mock(); // 43

mockFn.mockReturnValueOnce(value)

Raccourci pour :

jest.fn().mockImplementationOnce(() => value);

Accepte une valeur retournée pour un seul appel. Peut être chaînée pour que les appels successifs retournent des valeurs différentes. Quand il n'y a plus de valeurs mockReturnValueOnce, les appels retournent la valeur définie par mockReturnValue.

const mockFn = jest
.fn()
.mockReturnValue('default')
.mockReturnValueOnce('first call')
.mockReturnValueOnce('second call');

mockFn(); // 'first call'
mockFn(); // 'second call'
mockFn(); // 'default'
mockFn(); // 'default'

mockFn.mockResolvedValue(value)

Raccourci pour :

jest.fn().mockImplementation(() => Promise.resolve(value));

Utile pour simuler des fonctions asynchrones dans des tests async :

test('async test', async () => {
const asyncMock = jest.fn().mockResolvedValue(43);

await asyncMock(); // 43
});

mockFn.mockResolvedValueOnce(value)

Raccourci pour :

jest.fn().mockImplementationOnce(() => Promise.resolve(value));

Utile pour résoudre différentes valeurs sur plusieurs appels asynchrones :

test('async test', async () => {
const asyncMock = jest
.fn()
.mockResolvedValue('default')
.mockResolvedValueOnce('first call')
.mockResolvedValueOnce('second call');

await asyncMock(); // 'first call'
await asyncMock(); // 'second call'
await asyncMock(); // 'default'
await asyncMock(); // 'default'
});

mockFn.mockRejectedValue(value)

Raccourci pour :

jest.fn().mockImplementation(() => Promise.reject(value));

Utile pour créer des mocks async qui rejetteront toujours :

test('async test', async () => {
const asyncMock = jest
.fn()
.mockRejectedValue(new Error('Async error message'));

await asyncMock(); // throws 'Async error message'
});

mockFn.mockRejectedValueOnce(value)

Raccourci pour :

jest.fn().mockImplementationOnce(() => Promise.reject(value));

Utile avec .mockResolvedValueOnce() ou pour rejeter différentes exceptions lors de plusieurs appels asynchrones :

test('async test', async () => {
const asyncMock = jest
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error message'));

await asyncMock(); // 'first call'
await asyncMock(); // throws 'Async error message'
});

mockFn.withImplementation(fn, callback)

Accepte une fonction qui sera temporairement utilisée comme implémentation du mock pendant l'exécution du callback.

test('test', () => {
const mock = jest.fn(() => 'outside callback');

mock.withImplementation(
() => 'inside callback',
() => {
mock(); // 'inside callback'
},
);

mock(); // 'outside callback'
});

mockFn.withImplementation fonctionne que le callback soit asynchrone (retournant un thenable) ou non. Si le callback est asynchrone, une promesse est retournée. L'attente de cette promesse (avec await) attendra le callback et réinitialisera l'implémentation.

test('async test', async () => {
const mock = jest.fn(() => 'outside callback');

// We await this call since the callback is async
await mock.withImplementation(
() => 'inside callback',
async () => {
mock(); // 'inside callback'
},
);

mock(); // 'outside callback'
});

Propriétés remplacées

replacedProperty.replaceValue(value)

Modifie la valeur d'une propriété déjà remplacée. Utile pour ajuster des valeurs dans des tests spécifiques après remplacement initial. Alternative : appeler jest.replaceProperty() plusieurs fois sur la même propriété.

replacedProperty.restore()

Restaure la propriété de l'objet à sa valeur d'origine.

Notez que replacedProperty.restore() ne fonctionne que si la propriété a été remplacée via jest.replaceProperty().

L'option restoreMocks permet de restaurer automatiquement les propriétés remplacées avant chaque test.

Utilisation avec TypeScript

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

info

Les exemples TypeScript de cette page ne fonctionneront comme documenté que si vous importez explicitement les API Jest :

import {expect, jest, test} from '@jest/globals';

Consultez le guide Premiers pas pour plus de détails sur la configuration de Jest avec TypeScript.

jest.fn(implementation?)

Les typages corrects sont inférés si une implémentation est passée à jest.fn(). Dans les cas sans implémentation, passez un argument de type générique pour la sécurité typage (voir exemples) :

import {expect, jest, test} from '@jest/globals';
import type add from './add';
import calculate from './calc';

test('calculate calls add', () => {
// Create a new mock that can be used in place of `add`.
const mockAdd = jest.fn<typeof add>();

// `.mockImplementation()` now can infer that `a` and `b` are `number`
// and that the returned value is a `number`.
mockAdd.mockImplementation((a, b) => {
// Yes, this mock is still adding two numbers but imagine this
// was a complex function we are mocking.
return a + b;
});

// `mockAdd` is properly typed and therefore accepted by anything
// requiring `add`.
calculate(mockAdd, 1, 2);

expect(mockAdd).toHaveBeenCalledTimes(1);
expect(mockAdd).toHaveBeenCalledWith(1, 2);
});

jest.Mock<T>

Construit le type d'une fonction mock (type de retour de jest.fn()). Utile pour définir des fonctions mocks récursives :

import {jest} from '@jest/globals';

const sumRecursively: jest.Mock<(value: number) => number> = jest.fn(value => {
if (value === 0) {
return 0;
} else {
return value + fn(value - 1);
}
});

jest.Mocked<Source>

L'utilitaire jest.Mocked<Source> retourne le type Source encapsulé avec les définitions de type des fonctions mock Jest.

import {expect, jest, test} from '@jest/globals';
import type {fetch} from 'node-fetch';

jest.mock('node-fetch');

let mockedFetch: jest.Mocked<typeof fetch>;

afterEach(() => {
mockedFetch.mockClear();
});

test('makes correct call', () => {
mockedFetch = getMockedFetch();
// ...
});

test('returns correct data', () => {
mockedFetch = getMockedFetch();
// ...
});

Des types de classes, fonctions ou objets peuvent être passés comme argument de type à jest.Mocked<Source>. Si vous préférez contraindre le type d'entrée, utilisez : jest.MockedClass<Source>, jest.MockedFunction<Source> ou jest.MockedObject<Source>.

jest.Replaced<Source>

L'utilitaire jest.Replaced<Source> retourne le type Source encapsulé avec les définitions de type des propriétés remplacées Jest.

src/utils.ts
export function isLocalhost(): boolean {
return process.env['HOSTNAME'] === 'localhost';
}
src/__tests__/utils.test.ts
import {afterEach, expect, it, jest} from '@jest/globals';
import {isLocalhost} from '../utils';

let replacedEnv: jest.Replaced<typeof process.env> | undefined = undefined;

afterEach(() => {
replacedEnv?.restore();
});

it('isLocalhost should detect localhost environment', () => {
replacedEnv = jest.replaceProperty(process, 'env', {HOSTNAME: 'localhost'});

expect(isLocalhost()).toBe(true);
});

it('isLocalhost should detect non-localhost environment', () => {
replacedEnv = jest.replaceProperty(process, 'env', {HOSTNAME: 'example.com'});

expect(isLocalhost()).toBe(false);
});

jest.mocked(source, options?)

L'utilitaire mocked() encapsule les types de l'objet source et de ses membres imbriqués avec les définitions de fonctions mock Jest. Vous pouvez passer {shallow: true} comme argument options pour désactiver le mock profond.

Retourne l'objet source.

song.ts
export const song = {
one: {
more: {
time: (t: number) => {
return t;
},
},
},
};
song.test.ts
import {expect, jest, test} from '@jest/globals';
import {song} from './song';

jest.mock('./song');
jest.spyOn(console, 'log');

const mockedSong = jest.mocked(song);
// or through `jest.Mocked<Source>`
// const mockedSong = song as jest.Mocked<typeof song>;

test('deep method is typed correctly', () => {
mockedSong.one.more.time.mockReturnValue(12);

expect(mockedSong.one.more.time(10)).toBe(12);
expect(mockedSong.one.more.time.mock.calls).toHaveLength(1);
});

test('direct usage', () => {
jest.mocked(console.log).mockImplementation(() => {
return;
});

console.log('one more time');

expect(jest.mocked(console.log).mock.calls).toHaveLength(1);
});

jest.Spied<Source>

Construit le type d'une classe ou fonction espionnée (type de retour de jest.spyOn()).

__utils__/setDateNow.ts
import {jest} from '@jest/globals';

export function setDateNow(now: number): jest.Spied<typeof Date.now> {
return jest.spyOn(Date, 'now').mockReturnValue(now);
}
import {afterEach, expect, type jest, test} from '@jest/globals';
import {setDateNow} from './__utils__/setDateNow';

let spiedDateNow: jest.Spied<typeof Date.now> | undefined = undefined;

afterEach(() => {
spiedDateNow?.mockReset();
});

test('renders correctly with a given date', () => {
spiedDateNow = setDateNow(1_482_363_367_071);
// ...

expect(spiedDateNow).toHaveBeenCalledTimes(1);
});

Les types d'une classe ou d'une fonction peuvent être passés comme argument de type à jest.Spied<Source>. Si vous préférez contraindre le type d'entrée, utilisez : jest.SpiedClass<Source> ou jest.SpiedFunction<Source>.

Utilisez jest.SpiedGetter<Source> ou jest.SpiedSetter<Source> pour créer respectivement le type d'un accesseur ou mutateur espionné.