我正在尝试模拟对服务的调用,但我正在使用以下消息: jest.mock()
的模块工厂不允许引用任何超出范围的变量
我正在使用带有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:jest.mock()
的模块工厂不允许引用任何超出范围的变量。
变量访问无效:VocabularyEntry。
据我所知,我不能使用VocabularyEntry,因为它没有声明(因为jest将模拟定义移动到文件的顶部)。
任何人都可以解释我如何解决这个问题?我看到了需要引用的解决方案,但是我不知道如何使用类文件来执行此操作。
答案 0 :(得分:16)
如果您在升级到较新的Jest时出现类似错误[在我的情况下为19到21],您可以尝试将jest.mock
更改为jest.doMock
。
在此处找到 - https://github.com/facebook/jest/commit/6a8c7fb874790ded06f4790fdb33d8416a7284c8
答案 1 :(得分:9)
问题是所有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")]
}))
这将首先使用一个简单的间谍模拟模块,并在导入所有内容后设置模拟的真实实现。
答案 2 :(得分:2)
这就是我为你的代码解决它的方法。
您需要将模拟的组件存储在名为前缀为&#34; mock&#34;的变量中。 此解决方案基于我收到的错误消息末尾的注释。
注意:这是防范未初始化模拟的预防措施 变量。如果确保模拟是懒惰的,可变的 允许使用前缀为
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
});
答案 3 :(得分:1)
jest.mock("../../../src/services/vocabularyService", () => {
// eslint-disable-next-line global-require
const VocabularyEntry = require("../../../src/model/VocabularyEntry");
return {
vocabulary: [new VocabularyEntry("a", "a1")]
};
});
我认为它也应该与动态导入一起使用,而不是require
,但无法使其正常工作。
答案 4 :(得分:0)
对于我来说,这个问题是在我使用react-native-git-upgrade将react-native项目升级到v0.61之后开始的。
尽我所能之后。我决定清理项目并将所有测试恢复工作。
# react-native-clean-project
但是在运行react-native-clean-project时要当心,它可以清除所有ios和android文件夹(包括本机代码),因此在提示时仅回答N。就我而言,我只是选择了擦拭node_modules文件夹。