jest.resetModules()
可以清除所有模块的require缓存,但有没有一种方法可以仅清除单个模块的缓存?无法使用require.cache
,因为Jest似乎会绕过它。
我正在测试一个有状态的Node模块(即它依赖于多次调用require
返回相同的实例)。为了进行测试,我需要重置模块的状态以测试不同的场景。 jest.resetModules()
可以工作,但是我需要重新require
一些其他不需要重置的模拟模块。
如问题所述,jest.resetModules()
会重置模块缓存,在你的模块保留一些本地状态且需要在测试之间清除该状态时非常有用。
然而,resetModules 的问题在于它会重置所有内容,但有时您只想重置其中一些模块。
从 Jest 24 开始,您现在可以使用 jest.isolateModules
来实现此目的。
假设您有一个保留状态的模块:
module.js
exports.a = 1
exports.add = function (a) {
return exports.a += a;
}
模块.测试.js
test('adds 1 to counter', () => {
jest.isolateModules(() => {
const myModule = require('./module');
expect(myModule.add(1)).toBe(2);
expect(myModule.add(1)).toBe(3);
});
});
test('adds 2 to counter', () => {
jest.isolateModules(() => {
const myModule = require('./module');
expect(myModule.add(2)).toBe(3);
expect(myModule.add(2)).toBe(5);
});
});
基本上,在每次jest.isolateModules()调用之后,下一次要求该模块时,它将具有全新的状态。
jest.isolateModules()
或 jest.resetModules()
时,测试文件不会被视为从测试文件直接引用的模块的 module.parent
。其他文件仍然具有正确的 module.parent
。 - Garrett Motzner这是一个关于在测试文件中使用模块(包括工厂)进行模拟和还原的示例
describe("some tests", () => {
let subject;
describe("with mocks", () => {
beforeAll(() => {
jest.isolateModules(() => {
jest.doMock("some-lib", () => ({ someFn: jest.fn() })); // .doMock doesnt hoist like .mock does when using babel-jest
subject = require('./module-that-imports-some-lib');
});
});
// ... tests when some-lib is mocked
});
describe("without mocks - restoring mocked modules", () => {
beforeAll(() => {
jest.isolateModules(() => {
jest.unmock("some-lib");
subject = require('./module-that-imports-some-lib');
});
});
// ... tests when some-lib is NOT mocked
});
});
_moduleRegistry
并且你无法从测试环境内部访问它。我建议在上下文中添加一个新的方法,可以从模块注册表中删除单个模块。我建议在 repo 上开启一个问题,希望他们能够更新 Jest 以支持这个功能。 - ArcathresetModules()
进行单独测试。 - Gabriel Bleujest.mock( '../moduleName', () => { const myModule = importFresh('/path/to/module') }, {virtual: true}, );
?这将允许您加载模块的新副本,从而有效地重置模块以进行测试。importFresh
来自 https://github.com/sindresorhus/import-fresh - Mrchiefrequire
钩子,主要用于保持全局require
缓存的清洁和避免副作用。从你所做的事情来看,听起来你只需要模拟你想要使用的模块,然后确保在describe
块结束时清除它,你永远不应该让模拟模块留在那里供其他测试使用。如果你正确地设置和撤销你的模拟,你就不会遇到这个问题。你能提供一个更好的例子吗? - icirellik