Подтвердить что ты не робот

Служба, издевавшаяся со словами Jest: "Модуль factory для jest.mock() не может ссылаться на любые переменные вне области видимости" error

Я пытаюсь высмеять вызов службы, но я борюсь со следующим сообщением: Модуль factory jest.mock() не имеет права ссылаться на любые переменные вне области видимости.

Я использую babel с синтаксисом ES6, шуткой и ферментом.

У меня есть простой компонент, называемый Vocabulary, который получает список VocabularyEntry -Objects из vocabularyService и отображает его.

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
 }
 }

vocabularyServise ist очень просто:

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

  class VocabularyService {

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

Теперь я хочу издеваться над vocabularyService в тесте:

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

});

});

Запуск теста вызывает ошибку: Vocabulary.spec.js: babel-plugin-jest-hoist: Модуль factory of jest.mock() не может ссылаться на любые переменные вне области видимости. Недопустимый доступ к переменной: VocabularyEntry.

Насколько я не понял, я не могу использовать VocabularyEntry, потому что он не объявляет (поскольку jest переводит определение макета в верхнюю часть файла).

Может кто-нибудь объяснить, как я могу это исправить? Я видел решения, которые требовали, чтобы ссылки содержали макет-вызов, но я не понимаю, как это сделать с помощью файла класса.

4b9b3361

Ответ 1

Проблема в том, что все jest.mock будут подняты к вершине фактического блока кода во время компиляции, который в этом случае является вершиной файла. На данный момент VocabularyEntry не импортируется. Вы можете поместить mock в блок beforeAll в своем тесте или использовать jest.mock следующим образом:

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")]
}))

Это сначала будет издеваться над модулем с помощью простого шпиона, а после того, как все будет импортировано, оно устанавливает реальную реализацию макета.

Ответ 3

Вот как бы я решил это для вашего кода.

Вам нужно сохранить свой издеваемый компонент в переменной с именем, префиксом "mock". Это решение основано на примечании в конце сообщения об ошибке, которое я получал.

Примечание. Это предосторожность для защиты от неинициализированного макета переменные. Если обеспечивается, что макет требуется лениво, переменная разрешены имена с префиксом 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

});

Ответ 4

Глядя на https://github.com/facebook/jest/issues/2567

Вы можете попробовать jest.mock('../../../src/services/vocabularyService', () => ({ const VocabularyEntry= require('../model/VocabularyEntry'); // <= will probably need to be changed to be relative to test file vocabulary: [new VocabularyEntry("a", "a1")] }));

Сообщите мне, если это что-то делает.