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 afin 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 fonctionne pas la méthode' vraie?

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

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

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

  it('ne fonctionne pas la méthode', () => {
    // comment rendre cela 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 puisque 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 devraient sans que l'espion soit appelé à partir du test précédent. Vous pouvez également lire leur documentation à propos de cette fonctionnalité.

Option 2

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

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

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

77 votes

Il y a aussi jest.restoreAllMocks(); si vous voulez 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 ensemble de tests également. Cela est utile dans les cas où vous décidez de regrouper tous les tests pour une seule méthode sous un même ensemble de tests, mais vous voulez que les assertions n'aient pas en mémoire leurs valeurs précédentes.

79voto

sdgluck Points 9388

Les espions Jest ont la même API que les mocks. La documentation pour les 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.

Cela est souvent utile lorsque vous souhaitez nettoyer les données d'utilisation d'un mock entre deux assertions.

(mise en emphase de ma part)

Donc nous pouvons 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 afin que les assertions futures
       ne soient pas affectées par les appels 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 dans CodeSandbox.

5 votes

Il pourrait être souhaitable de mettre à jour ceci. À ce jour, en utilisant Jasmine ~2.8.6 et jest 24.0.9, ceci est incorrect. 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 correcte selon la documentation de Jest. Veuillez consulter le lien que j'ai mis à la fin de ma réponse qui le démontre en train de fonctionner dans CodeSandbox.

2 votes

...eh bien alors... Je suppose que j'ai juste essayé de le faire fonctionner un jour où la plaisanterie était en train de prendre son envol. Ce ne serait pas la première fois qu'une bibliothèque décide d'être difficile et de ne pas fonctionner comme prévu.

30voto

Daniel Dantas Points 171

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

Consultez l'exemple ci-dessous:

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

const myObject = new MyClass();
const mockMyBooleanMethod = jest.spyOn(myObject, 'myBooleanMethod', 'get');
// simuler que myBooleanMethod renvoie false
mockMyBooleanMethod.mockReturnValue(false);
// restaurer myBooleanMethod à son comportement d'origine
mockMyBooleanMethod.mockRestore();

0 votes

Merci @Daniel, celui-ci était 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 2è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 perdu quelques heures, c'est la seule solution qui fonctionne

16voto

James Irwin Points 561

En allant plus loin dans 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,
...
}

Consultez la documentation ici.

2voto

Jeremy Points 329

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

Réf : 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