web-dev-qa-db-fra.com

Le service simulé avec Jest provoque l'erreur «La fabrique de modules de jest.mock () n'est pas autorisée à référencer les variables hors de portée»

J'essaie de simuler un appel à un service, mais je me bats avec le message suivant: La fabrique de modules de jest.mock() n'est pas autorisée à référencer des variables hors de portée =.

J'utilise babel avec la syntaxe ES6, la plaisanterie et l'enzyme.

J'ai un composant simple appelé Vocabulary qui obtient une liste de VocabularyEntry- objets à partir d'un vocabularyService et le rend.

import React from 'react';
import vocabularyService from '../services/vocabularyService';

export default class Vocabulary extends React.Component {

render() {

    let rows = vocabularyService.vocabulary.map((v, i) => <tr key={i}>
            <td>{v.src}</td>
            <td>{v.target}</td>
        </tr>
    );
    // render rows
 }
 }

Le vocabularyServise est très simple:

  import {VocabularyEntry} from '../model/VocabularyEntry';

  class VocabularyService {

  constructor() {
       this.vocabulary = [new VocabularyEntry("a", "b")];
  }
} 
export default new VocabularyService();`

Maintenant, je veux me moquer du vocabularyService dans un test:

import {shallow} from 'enzyme';
import React from 'react';
import Vocabulary from "../../../src/components/Vocabulary ";
import {VocabularyEntry} from '../../../src/model/VocabularyEntry'

jest.mock('../../../src/services/vocabularyService', () => ({

vocabulary: [new VocabularyEntry("a", "a1")]

}));

describe("Vocabulary tests", () => {

test("renders the vocabulary", () => {

    let $component = shallow(<Vocabulary/>);

    // expect something

});

});

L'exécution du test provoque une erreur: Vocabulary.spec.js: babel-plugin-jest-hoist: la fabrique de modules de jest.mock() n'est pas autorisée à référencer des variables hors de portée. Accès variable non valide: VocabularyEntry.

Pour autant que je ne l'ai pas compris, je ne peux pas utiliser le VocabularyEntry car il n'est pas déclaré (car jest déplace la définition fictive en haut du fichier).

Quelqu'un peut-il expliquer comment je peux résoudre ce problème? J'ai vu des solutions qui nécessitaient les références dans le faux appel mais je ne comprends pas comment je peux le faire avec un fichier de classe.

18
Ria

Le problème est que tous les jest.mock sera hissé en haut du bloc de code réel au moment de la compilation, qui est dans ce cas le haut du fichier. À ce stade, VocabularyEntry n'est pas importé. Vous pouvez soit placer le mock dans un bloc beforeAll dans votre test, soit utiliser jest.mock comme ça:

import {shallow} from 'enzyme';
import React from 'react';
import Vocabulary from "../../../src/components/Vocabulary ";
import {VocabularyEntry} from '../../../src/model/VocabularyEntry'
import vocabularyService from '../../../src/services/vocabularyService'

jest.mock('../../../src/services/vocabularyService', () => jest.fn())

vocabularyService.mockImplementation(() => ({
  vocabulary: [new VocabularyEntry("a", "a1")]
}))

Cela se moquera d'abord du module avec un simple espion et après que tout le matériel soit importé, il définira la véritable implémentation de la maquette.

12
Andreas Köberle

Si vous obtenez une erreur similaire lors de la mise à niveau vers une version plus récente de Jest [19 à 21 dans mon cas], vous pouvez essayer de modifier jest.mock à jest.doMock.

Trouvé ceci ici - https://github.com/facebook/jest/commit/6a8c7fb874790ded06f4790fdb33d8416a7284c8

17
Misha Reyzlin

C'est ainsi que je le résoudrais pour votre code.

Vous devez stocker votre composant simulé dans une variable avec un nom préfixé par "simulé". Cette solution est basée sur la note à la fin du message d'erreur que je recevais.

Remarque: Il s'agit d'une précaution pour se prémunir contre les variables factices non initialisées. S'il est garanti que la maquette est requise paresseusement, les noms de variables précédés de mock sont autorisés.

import {shallow} from 'enzyme';
import React from 'react';
import Vocabulary from "../../../src/components/Vocabulary ";
import {VocabularyEntry} from '../../../src/model/VocabularyEntry'

const mockVocabulary = () => new VocabularyEntry("a", "a1");

jest.mock('../../../src/services/vocabularyService', () => ({
    default: mockVocabulary
}));

describe("Vocabulary tests", () => {

test("renders the vocabulary", () => {

    let $component = shallow(<Vocabulary/>);

    // expect something

});
6
maxletou