node.js require()缓存-可能无效?

从node.js文档中:

第一次加载模块后将对其进行缓存。这意味着(除其他事项外)每次对require('foo')的调用都将获得与返回的对象完全相同的对象(如果它将解析为相同的文件)。

有没有办法使该缓存无效?即对于单元测试,我希望每个测试都可以在一个新对象上进行。

阳光前端2020/03/18 17:55:40

如果用于单元测试,则另一个好的工具是proxyquire每次您代理查询模块时,它将使模块缓存无效并缓存一个新的模块。它还允许您修改要测试的文件所需的模块。

小哥凯小小2020/03/18 17:55:39

我会再向luff的答案添加一行,并更改参数名称:

function requireCached(_module){
    var l = module.children.length;
    for (var i = 0; i < l; i++)
    {
        if (module.children[i].id === require.resolve(_module))
        {
            module.children.splice(i, 1);
            break;
        }
    }
    delete require.cache[require.resolve(_module)];
    return require(_module)
}
小卤蛋LEY2020/03/18 17:55:39

我不能100%地确定“无效”是什么意思,但是您可以在require语句上方添加以下内容以清除缓存:

Object.keys(require.cache).forEach(function(key) { delete require.cache[key] })

从@ Dancrumb的评论采取这里

猪猪小宇宙2020/03/18 17:55:39

对于使用Jest的任何人,因为Jest进行自己的模块缓存,所以有一个内置函数-只需确保jest.resetModules运行例如。在每个测试之后:

afterEach( function() {
  jest.resetModules();
});

尝试使用decache就像建议另一个答案后,发现了这一点感谢Anthony Garvan

功能文档在这里

小卤蛋卡卡西2020/03/18 17:55:39

rewire非常适合此用例,每次调用都会获得一个新实例。轻松的依赖注入,用于node.js单元测试。

rewire在模块中添加了一个特殊的setter和getter,因此您可以修改它们的行为以进行更好的单元测试。你可以

为其他模块或全局变量(例如进程泄漏专用变量)注入模拟,将覆盖模块内的变量。rewire不会加载文件并评估内容以模拟节点的require机制。实际上,它使用节点自身的要求来加载模块。因此,您的模块在测试环境中的行为与常规情况下完全一样(修改除外)。

对所有咖啡因上瘾者来说是个好消息:rewire也可以在Coffee-Script中使用。请注意,在这种情况下,需要在devDependencies中列出CoffeeScript。