Aller au contenu principal
Version: 27.0

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()#

Renvoie la chaîne du nom de la simulation définie en appelant mockFn.mockName(value).

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.mockClear()#

Resets all information stored in the mockFn.mock.calls, mockFn.mock.instances and mockFn.mock.results arrays. Often this is useful when you want to clean up a mocks usage data between two assertions.

Beware that mockClear will replace mockFn.mock, not just these three properties! 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. L'option de configuration clearMocks est disponible pour effacer les simulations automatiquement entre les tests.

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. (Notez que la réinitialisation d'un espion se traduira par une fonction sans valeur de retour).

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.

Attention, mockFn.mockRestore ne fonctionne que lorsque la simulation a été créée avec jest.spyOn. Vous devez donc vous occuper vous-même de la restauration lorsque vous assignez manuellement jest.fn().

L'option de configuration restoreMocks est disponible pour restaurer les simulations automatiquement entre les tests.

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.

Remarque : 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'); // this happens automatically with automocking
const SomeClass = require('./SomeClass');
const mMock = jest.fn();
SomeClass.mockImplementation(() => {
return {
m: mMock,
};
});
const some = new SomeClass();
some.m('a', 'b');
console.log('Calls to 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(value)#

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 mock function "mockedFunction" to have been called, but it was not called.

mockFn.mockReturnThis()#

Fonction de sucre syntaxique pour :

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

mockFn.mockReturnValue(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)#

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)#

Fonction de sucre syntaxique pour :

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)#

Fonction de sucre syntaxique pour :

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)#

Fonction de sucre syntaxique pour :

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)#

Fonction de sucre syntaxique pour :

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#

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');
// Notre simulation de `add` est maintenant entièrement typée
const mockAdd = add as jest.MockedFunction<typeof add>;
test('calculate appelle add', () => {
calculate('Add', 1, 2);
expect(mockAdd).toBeCalledTimes(1);
expect(mockAdd).toBeCalledWith(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).toBeCalledTimes(1);
expect(mockAdd).toBeCalledWith(1, 2);
});

jest.MockedClass#

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`. À la place, vous pouvez vérifier les appels à une méthode
// comme celle-ci entièrement typée :
expect(SoundPlayerMock.prototype.playSoundFile.mock.calls[0][0]).toEqual(
coolSoundFileName,
);
// équivalent à la vérification ci-dessus :
expect(SoundPlayerMock.prototype.playSoundFile).toHaveBeenCalledWith(
coolSoundFileName,
);
expect(SoundPlayerMock.prototype.playSoundFile).toHaveBeenCalledTimes(1);
});