Estoy tratando de simular una llamada a un servicio, pero estoy luchando con el siguiente mensaje: La fábrica de módulos de jest.mock() no puede hacer referencia a ninguna variable fuera del alcance .
Estoy usando babel con sintaxis ES6, broma y enzima.
Tengo un componente simple llamado Vocabulary que obtiene una lista de VocabularyEntry -Objects de un vocabularyService y la representa.
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 } } El servicio de vocabularyServise es muy simple:
import {VocabularyEntry} from '../model/VocabularyEntry'; class VocabularyService { constructor() { this.vocabulary = [new VocabularyEntry("a", "b")]; } } export default new VocabularyService();` Ahora quiero simular el servicio de vocabularyService en una prueba:
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 });});
La ejecución de la prueba genera un error: Vocabulary.spec.js: babel-plugin-jest-hoist: la fábrica de módulos de jest.mock() no puede hacer referencia a ninguna variable fuera del alcance. Acceso variable no válido: VocabularyEntry.
Por lo que entendí, no puedo usar VocabularyEntry porque no se declara (ya que la broma mueve la definición simulada a la parte superior del archivo).
¿Alguien puede explicar cómo puedo solucionar esto? Vi soluciones que requerían las referencias dentro de la llamada simulada, pero no entiendo cómo puedo hacer esto con un archivo de clase.
Debe almacenar su componente simulado en una variable con un nombre precedido por "simulacro". Esta solución se basa en la nota al final del mensaje de error que recibí.
Nota: Esta es una precaución para protegerse contra variables simuladas no inicializadas. Si se garantiza que el simulacro se requiere de forma perezosa, se permiten nombres de variables con el prefijo
mock.
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 });El problema es que todo jest.mock se elevará a la parte superior del bloque de código real en el momento de la compilación, que en este caso es la parte superior del archivo. En este punto VocabularyEntry no se importa. Puede colocar el mock en un bloque beforeAll en su prueba o usar jest.mock de esta manera:
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")] }))Esto primero simulará el módulo con un simple espía y, después de importar todo el material, establecerá la implementación real del simulacro.
Si obtiene un error similar al actualizar a Jest más nuevo [19 a 21 en mi caso], puede intentar cambiar jest.mock a jest.doMock .
Encontré esto aquí: https://github.com/facebook/jest/commit/6a8c7fb874790ded06f4790fdb33d8416a7284c8