197 votes

Comment réinitialiser ou effacer un espion dans Jest ?

J'ai un espion qui est utilisé dans plusieurs assertions à travers plusieurs tests dans une suite.

Comment puis-je effacer ou réinitialiser l'espion de sorte que dans chaque test la méthode que l'espion intercepte soit considérée comme n'ayant pas été invoquée?

Par exemple, comment rendre l'assertion dans 'ne pas exécuter la méthode' vraie?

const methods = {
  run: () => {}
}

const spy = jest.spyOn(methods, 'run')

describe('espion', () => {
  it('exécute la méthode', () => {
    methods.run()
    expect(spy).toHaveBeenCalled() //=> true
  })

  it('ne pas exécuter la méthode', () => {
    // comment rendre ceci vrai?
    expect(spy).not.toHaveBeenCalled() //=> false
  })
})

261voto

ghiscoding Points 1519

Merci à @sdgluck pour la réponse, bien que je voudrais ajouter à cette réponse que dans mon cas, je voulais un état clair après chaque test car j'ai plusieurs tests avec le même espion. Donc au lieu d'appeler mockClear() dans le(s) test(s) précédent(s), je l'ai déplacé dans le afterEach() (ou vous pouvez l'utiliser avec beforeEach) comme ceci :

afterEach(() => {    
  jest.clearAllMocks();
});

Et enfin, mes tests fonctionnent comme ils le devraient sans que l'espion ne soit appelé depuis le test précédent. Vous pouvez également consulter leur documentation à propos de cette fonctionnalité.

Option 2

Si vous souhaitez le faire au niveau global, vous pourriez également mettre à jour votre jest.config.js (ou depuis package.json) ce qui effacera l'espion à chaque test sans avoir à appeler jest.clearAllMocks() à chaque test.

module.exports = {
  clearMocks: true,
  // ...
}

Vous pouvez consulter la documentation de Jest à propos de cette fonctionnalité.

77 votes

Il y a aussi jest.restoreAllMocks(); si vous souhaitez restaurer les fonctions simulées à leurs implémentations d'origine!

17 votes

Vous pouvez également ajouter restoreMocks: true à votre configuration Jest pour qu'il appelle automatiquement restoreAllMocks() après chaque test. Personnellement, je n'ai aucune raison de laisser les mocks persister entre deux tests, donc j'aime les réinitialiser tous aveuglément entre chaque test sans avoir à l'écrire dans le bloc afterEach() en tant qu'élément de nettoyage.

2 votes

Vous pouvez appeler jest.clearAllMocks(); entre deux assertions dans le même test suite également. Cela est utile pour les cas dans lesquels vous décidez de regrouper tous les tests pour une seule méthode sous un `test suite`, mais vous voulez que les assertions n'aient pas à se souvenir de leurs valeurs précédentes.

79voto

sdgluck Points 9388

Les espions Jest ont la même API que les mocks. La documentation des mocks se trouve ici et spécifie une méthode mockClear qui:

Réinitialise toutes les informations stockées dans les tableaux mockFn.mock.calls et mockFn.mock.instances.

Très souvent, cela est utile lorsque vous souhaitez nettoyer les données d'utilisation d'un mock entre deux assertions.

(mes propres emphases)

Nous pouvons donc utiliser mockClear pour "réinitialiser" un espion. En utilisant votre exemple:

const methods = {
  run: () => {}
}

const spy = jest.spyOn(methods, 'run')

describe('spy', () => {
  it('exécute la méthode', () => {
    methods.run()
    expect(spy).toHaveBeenCalled() //=> true
    /* nettoyer l'espion pour que les assertions futures
       ne soient pas affectées par les invocations de la méthode
       dans ce test */
    spy.mockClear()
  })

  it('n'exécute pas la méthode', () => {
    expect(spy).not.toHaveBeenCalled() //=> true
  })
})

Voici un exemple sur CodeSandbox.

5 votes

Il pourrait être bon de mettre à jour ceci. Aujourd'hui, en utilisant Jasmine ~2.8.6 et jest 24.0.9, ceci n'est pas correct. La propriété 'mockClear' n'existe pas sur le type 'Spy'.

0 votes

@Bardicer Cette approche fonctionne toujours dans la dernière version de Jest, et est conforme à la documentation de Jest. Veuillez consulter le lien que j'ai ajouté à la fin de ma réponse pour le voir fonctionner dans CodeSandbox.

2 votes

... Eh bien alors... Je suppose que j'ai juste essayé de le faire fonctionner un jour où l'humeur était à la plaisanterie. Ce ne serait pas la première fois qu'une bibliothèque décide simplement de poser problème et de ne pas fonctionner comme prévu.

30voto

Daniel Dantas Points 171

Si vous souhaitez restaurer le comportement d'origine d'une méthode que vous aviez précédemment ajoutée à un espion, vous pouvez utiliser la méthode mockRestore.

Jetez un œil à l'exemple ci-dessous:

class MyClass {
    get myBooleanMethod(): boolean {
        return true;
    }
}

const myObject = new MyClass();
const mockMyBooleanMethod = jest.spyOn(myObject, 'myBooleanMethod', 'get');
// mock myBooleanMethod to return false
mockMyBooleanMethod.mockReturnValue(false);
// restore myBooleanMethod to its original behavior
mockMyBooleanMethod.mockRestore();

0 votes

Merci @Daniel, celui-ci a été le seul qui a fonctionné pour moi dans ma situation où le test cassé faisait spy = jest.spyOn(document) ce qui devait être fait deux fois et la deuxième fois causera "TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.".

0 votes

Même ici, après avoir gaspillé quelques heures, c'est la seule solution qui fonctionne

16voto

James Irwin Points 561

En approfondissant la réponse de @ghiscoding, vous pouvez spécifier clearMocks dans la configuration de Jest, ce qui équivaut à appeler jest.clearAllMocks() entre chaque test :

{
...
    clearMocks: true,
...
}

Voir la documentation ici.

2voto

Jeremy Points 329

MODIFIER : Dans jest.config.js ajoutez resetMocks - pas clearMocks, car cela ne supprimera pas toute implémentation simulée entre les tests (c'est-à-dire que resetMocks est l'option plus prudente et supprimera l'implémentation entre les tests - ce qui, à mon avis, est la bonne chose à faire puisque chaque test est censé être isolé).

Référence : https://jestjs.io/docs/configuration#resetmocks-boolean

{
...
    resetMocks: true,
...
}

En plus de cela, vous pourriez également appeler jest.resetAllMocks() dans beforeEach ou afterEach.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X