使用 Jest 模拟的服务导致“不允许 jest.mock() 的模块工厂引用任何超出范围的变量”错误

新手上路,请多包涵

我正在尝试模拟对服务的调用,但遇到以下消息: The module factory of jest.mock() is not allowed to reference any out-of-scope variables

我正在使用带有 ES6 语法、笑话和酶的 babel。

我有一个名为 Vocabulary 的简单组件,它获取 VocabularyEntry 来自 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 非常简单:

 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: The module factory of jest.mock() is not allowed to reference any out-of-scope variables。无效的变量访问:VocabularyEntry。

据我了解,我不能使用 VocabularyEntry 因为它没有声明(因为开玩笑将模拟定义移动到文件的顶部)。

谁能解释我如何解决这个问题?我看到了需要在模拟调用中引用的解决方案,但我不明白如何使用类文件来做到这一点。

原文由 Ria 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

问题是所有 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")]
}))

这将首先使用一个简单的 spy 模拟模块,然后在导入所有内容后,它会设置模拟的实际实现。

原文由 Andreas Köberle 发布,翻译遵循 CC BY-SA 4.0 许可协议

您需要将模拟组件存储在名称以“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

});

原文由 maxletou 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进