Aller au contenu principal
Version : 27.x

Fonctions simulées

Les fonctions simulées sont également connues sous le nom d'« espions », car elles vous permettent d'espionner le comportement d'une fonction qui est appelée indirectement par un autre code, plutôt que de tester uniquement la sortie. Vous pouvez créer une fonction simulée avec jest.fn(). Si aucune implémentation n’est donnée, la fonction simulée retournera undefined lorsqu’elle est appelée.

Méthodes


Référence

mockFn.getMockName()

Returns the mock name string set by calling .mockName().

mockFn.mock.calls

Un tableau contenant les arguments d'appel de tous les appels qui ont été faits à cette fonction simulée. Chaque élément du tableau est un tableau d'arguments qui ont été passés pendant l'appel.

Par exemple : Une fonction simulée f qui a été appelée deux fois, avec les arguments f('arg1', 'arg2'), puis avec les arguments f('arg3', 'arg4'), aurait un tableau mock.calls qui ressemble à ceci :

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

mockFn.mock.results

Un tableau contenant les résultats de tous les appels qui ont été faits à cette fonction simulée. Chaque entrée de ce tableau est un objet contenant une propriété type, et une propriété value. type sera l'un des suivants :

  • 'return' - Indique que l'appel s'est terminé en retournant normalement.
  • 'throw' - Indique que l'appel s'est terminé en levant une valeur.
  • 'incomplete' - Indique que l'appel n'est pas encore terminé. Cela se produit si vous testez le résultat à partir de la fonction simulée elle-même, ou à partir d'une fonction qui a été appelée par la fonction simulée.

La propriété value contient la valeur qui a été levée ou retournée. value est indéfinie lorsque type === 'incomplete'.

Par exemple : Une fonction simulée f qui a été appelée trois fois, renvoyant 'result1', lançant une erreur, puis renvoyant 'result2', aurait un tableau mock.results qui ressemble à ceci :

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

mockFn.mock.instances

Un tableau qui contient toutes les instances d'objet qui ont été instanciées à partir de cette fonction simulée en utilisant new.

Par exemple : Une fonction simulée qui a été instanciée deux fois aurait 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.lastCall

Un tableau contenant les arguments d'appel du dernier appel qui a été fait à cette fonction simulée. Si la fonction n'a pas été appelée, elle retournera undefined.

Par exemple : Une fonction simulée f qui a été appelée deux fois, avec les arguments f('arg1', 'arg2'), puis avec les arguments f('arg3', 'arg4'), aurait un tableau mock.lastCall qui ressemble à ceci :

['arg3', 'arg4'];

mockFn.mockClear()

Efface toutes les informations stockées dans les tableaux mockFn.mock.calls, mockFn.mock.instances et mockFn.mock.results. Souvent, cela est utile lorsque vous voulez nettoyer les données d'utilisation d'une simulation entre deux assertions.

L'option de configuration clearMocks est disponible pour effacer les simulations automatiquement avant chaque test.

danger

Attention, mockClear remplacera mockFn.mock, pas seulement ces trois propriétés ! Vous devriez donc éviter d'assigner mockFn.mock à d'autres variables, temporaires ou non, pour être sûr de ne pas accéder à des données périmées.

mockFn.mockReset()

Fait tout ce que mockFn.mockClear() fait, et supprime également toute valeur de retour ou d'implémentation simulées.

Ceci est utile lorsque vous voulez réinitialiser complètement une simulation à son état initial.

The resetMocks configuration option is available to reset mocks automatically before each test.

info

Resetting a mock created with jest.spyOn() will result in a function with no return value.

mockFn.mockRestore()

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

Ceci est utile lorsque vous voulez simuler des fonctions dans certains cas de test et restaurer l'implémentation originale dans d'autres.

L'option de configuration restoreMocks est disponible pour restaurer les simulations automatiquement avant chaque test.

info

mockFn.mockRestore only works when the mock was created with jest.spyOn. Vous devez donc vous occuper vous-même de la restauration lorsque vous assignez manuellement jest.fn().

mockFn.mockImplementation(fn)

Accepte une fonction qui doit être utilisée comme l'implémentation de simulation. La simulation elle-même enregistrera toujours tous les appels qui entrent et les instances qui proviennent d'elle - la seule différence est que l'implémentation sera également exécutée lorsque la simulation est appelée.

astuce

jest.fn(implémentation) est un raccourci pour jest.fn().mockImplementation(implémentation).

Par exemple :

const mockFn = jest.fn().mockImplementation(scalar => 42 + scalar);
// ou : jest.fn(scalar => 42 + scalar);

const a = mockFn(0);
const b = mockFn(1);

a === 42; // true
b === 43; // true

mockFn.mock.calls[0][0] === 0; // true
mockFn.mock.calls[1][0] === 1; // true

mockImplementation peut également être utilisé pour simuler les constructeurs de classes :

SomeClass.js
module.exports = class SomeClass {
m(a, b) {}
};
OtherModule.test.js
jest.mock('./SomeClass'); // cela se produit automatiquement avec l'auto-simulation
const SomeClass = require('./SomeClass');
const mMock = jest.fn();
SomeClass.mockImplementation(() => {
return {
m: mMock,
};
});

const some = new SomeClass();
some.m('a', 'b');
console.log('Appels à m: ', mMock.mock.calls);

mockFn.mockImplementationOnce(fn)

Accepte une fonction qui sera utilisée comme une implémentation de simulation pour un appel à la fonction simulée. Peut être enchaîné de sorte que plusieurs appels de fonction produisent des résultats différents.

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

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

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

Lorsque la fonction simulée manque d'implémentations définies avec mockImplementationOnce, elle exécutera l'implémentation par défaut définie avec jest.fn(() => defaultValue) ou .mockImplementation(() => defaultValue) s'ils ont été appelés :

const myMockFn = jest
.fn(() => 'par défaut')
.mockImplementationOnce(() => 'premier appel')
.mockImplementationOnce(() => 'second appel');

// 'premier appel', 'second appel', 'par défaut', 'par défaut'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());

mockFn.mockName(name)

Accepte une chaîne à utiliser dans le résultat du test à la place de 'jest.fn()' pour indiquer quelle fonction simulée est référencée.

Par exemple :

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

Le résultat est cette erreur :

expect(mockedFunction).toHaveBeenCalled()

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

mockFn.mockReturnThis()

Shorthand for:

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

mockFn.mockReturnValue(value)

Shorthand for:

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

Accepte une valeur qui sera retournée chaque fois que la fonction simulée est appelée.

const mock = jest.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43

mockFn.mockReturnValueOnce(value)

Shorthand for:

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

Accepte une valeur qui sera retournée pour un appel à la fonction simulée. Peut être enchaîné de sorte que les appels successifs à la fonction simulée retournent des valeurs différentes. Quand il n'y a plus de valeurs mockReturnValueOnce à utiliser, les appels retourneront une valeur spécifiée par mockReturnValue.

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

// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());

mockFn.mockResolvedValue(value)

Shorthand for:

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

Utile pour simuler les fonctions asynchrones dans les tests asynchrones :

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

await asyncMock(); // 43
});

mockFn.mockResolvedValueOnce(value)

Shorthand for:

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

Utile pour résoudre des valeurs différentes 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)

Shorthand for:

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

Utile pour créer des fonctions simulées asynchrones qui seront toujours rejetées :

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

await asyncMock(); // throws "Async error"
});

mockFn.mockRejectedValueOnce(value)

Shorthand for:

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

Exemple d'utilisation :

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

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

TypeScript

Jest lui-même est écrit en TypeScript.

Si vous utilisez Create React App, alors le template TypeScript contient tout ce dont vous avez besoin pour commencer à écrire des tests en TypeScript.

Sinon, veuillez consulter notre guide Premiers pas pour l'installation avec TypeScript.

You can see an example of using Jest with TypeScript in our GitHub repository.

jest.MockedFunction

astuce

jest.MockedFunction est disponible dans le module @types/jest de la version 24.9.0.

Les exemples suivants considéreront que vous avez une compréhension de la façon dont les fonctions de simulation de Jest fonctionnent avec JavaScript.

Vous pouvez utiliser jest.MockedFunction pour représenter une fonction qui a été remplacée par une simulation Jest.

Exemple en utilisant jest.mock automatique `` :

// Supposons que `add` est importé et utilisé dans `calculate`.
import add from './add';
import calculate from './calc';

jest.mock('./add');

// Our mock of `add` is now fully typed
const mockAdd = add as jest.MockedFunction<typeof add>;

test('calculate calls add', () => {
calculate('Add', 1, 2);

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

Exemple en utilisant jest.fn :

// Ici, `add` est importé pour son type
import add from './add';
import calculate from './calc';

test('calculate appelle add', () => {
// Crée une nouvelle simulation qui peut être utilisé à la place de `add`.
const mockAdd = jest.fn() as jest.MockedFunction<typeof add>;

// Remarque : Vous pouvez utiliser le type `jest.fn` directement comme ceci si vous voulez :
// const mockAdd = jest.fn<ReturnType<typeof add>, Parameters<typeof add>>();
// `jest.MockedFunction` est un raccourci plus convivial.

// Maintenant, nous pouvons facilement mettre en place des implémentations simulées.
// Toute l'API `.mock*` peut maintenant vous donner les types appropriés pour `add`.
// https://jestjs.io/docs/mock-function-api

// `.mockImplementation` peut maintenant déduire que `a` et `b` sont des `number`
// et que la valeur renvoyée est un `number`.
mockAdd.mockImplementation((a, b) => {
// Oui, cette fonction simulée ajoute toujours deux nombres mais imaginez que
// c'est une fonction complexe que nous simulons.
return a + b
});

// `mockAdd` est correctement typé et donc accepté par
// tout ce que requiert `add`.
calculate(mockAdd, 1, 2);

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

jest.MockedClass

astuce

jest.MockedClass est disponible dans le module @types/jest de la version 24.9.0.

Les exemples suivants considéreront que vous avez une compréhension de la façon dont les classes de simulation de Jest fonctionnent avec JavaScript.

Vous pouvez utiliser jest.MockedClass pour représenter une classe qui a été remplacée par une simulation Jest.

La conversion de l'exemple de la classe ES6 automatiquement simulée ressemblerait à ceci :

import SoundPlayer from '../sound-player';
import SoundPlayerConsumer from '../sound-player-consumer';

jest.mock('../sound-player'); // SoundPlayer est maintenant un constructeur simulé

const SoundPlayerMock = SoundPlayer as jest.MockedClass<typeof SoundPlayer>;

beforeEach(() => {
// Supprime toutes les instances et les appels au constructeur et à toutes les méthodes :
SoundPlayerMock.mockClear();
});

it('Nous pouvons vérifier si le consommateur a appelé le constructeur de la classe', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
expect(SoundPlayerMock).toHaveBeenCalledTimes(1);
});

it('Nous pouvons vérifier si le consommateur a appelé une méthode sur l\'instance de la classe', () => {
// Montre que mockClear() fonctionne :
expect(SoundPlayerMock).not.toHaveBeenCalled();

const soundPlayerConsumer = new SoundPlayerConsumer();
// Le constructeur aurait dû être appelé à nouveau :
expect(SoundPlayerMock).toHaveBeenCalledTimes(1);

const coolSoundFileName = 'song.mp3';
soundPlayerConsumer.playSomethingCool();

// mock.instances est disponible avec les simulations automatiques :
const mockSoundPlayerInstance = SoundPlayerMock.mock.instances[0];

// Cependant, il ne permettra pas l'accès à `.mock` en TypeScript
// car il renvoie `SoundPlayer`. Instead, you can check the calls to a
// method like this fully typed:
expect(SoundPlayerMock.prototype.playSoundFile.mock.calls[0][0]).toBe(
coolSoundFileName,
);
// Equivalent to above check:
expect(SoundPlayerMock.prototype.playSoundFile).toHaveBeenCalledWith(
coolSoundFileName,
);
expect(SoundPlayerMock.prototype.playSoundFile).toHaveBeenCalledTimes(1);
});