在node.js文档中:

模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。

是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。


当前回答

文件说:

当需要模块时,模块缓存在这个对象中。通过从该对象中删除键值,下一个require将重新加载该模块。这不适用于本机插件,因为重新加载将导致错误。

其他回答

如果是用于单元测试,另一个可以使用的好工具是proxyquire。每次你代理模块时,它都会使模块缓存失效,并缓存一个新的模块。它还允许您修改正在测试的文件所需的模块。

以下两步程序对我来说非常有效。

在动态更改模型文件i-e 'mymodule.js'后,你需要先删除预编译的模型,然后使用require-reload重新加载它

Example:
        // Delete mongoose model
        delete mongoose.connection.models[thisObject.singular('mymodule')]

        // Reload model
        var reload = require('require-reload')(require);
        var entityModel = reload('./mymodule.js');

有一个简单模块(带测试)

我们在测试代码时遇到了这个问题(删除缓存模块,以便它们可以在新鲜状态下重新使用),所以我们审查了人们在各种StackOverflow问答上的所有建议,并将一个简单的node.js模块(带测试)放在一起:

https://www.npmjs.com/package/decache

如你所料,它既适用于已发布的npm包,也适用于本地定义的模块。Windows, Mac, Linux等等。

怎么做?(使用)

用法非常简单:

安装

从npm安装模块:

NPM安装decache——save-dev

在你的代码中使用它:

// require the decache module:
const decache = require('decache');

// require a module that you wrote"
let mymod = require('./mymodule.js');

// use your module the way you need to:
console.log(mymod.count()); // 0   (the initial state for our counter is zero)
console.log(mymod.incrementRunCount()); // 1

// delete the cached module:
decache('./mymodule.js');

//
mymod = require('./mymodule.js'); // fresh start
console.log(mymod.count()); // 0   (back to initial state ... zero)

如果你有任何问题或需要更多的例子,请创建一个GitHub问题: https://github.com/dwyl/decache/issues

下面是我对这个问题的回答,它处理如果文件有(例如)语法错误就不加载的问题

function reacquire(module) {
const fullpath  = require.resolve(module);
const backup = require.cache[fullpath];
delete require.cache[fullpath];

 try {
   const newcopy = require(module);
   console.log("reqcquired:",module,typeof newcopy);
   return newcopy;
 } catch (e) {
    console.log("Can't reqcquire",module,":",e.message);
    require.cache[fullpath] = backup;
    return backup;
 }

}

对于这个用例,重新连接非常有用,每次调用都会得到一个新实例。简单的依赖注入node.js单元测试。

Rewire为模块添加了一个特殊的setter和getter,这样您就可以修改它们的行为以进行更好的单元测试。你可能

为其他模块或全局变量(如process)注入mock 泄露私有变量 重写模块内的变量。 Rewire不会加载文件并计算内容以模拟节点的require机制。实际上,它使用节点自己的require来加载模块。因此,您的模块在测试环境中的行为与常规情况下完全相同(除了您的修改)。

对所有咖啡因成瘾者来说,这是个好消息:重新连接也适用于Coffee-Script。注意,在这种情况下CoffeeScript需要被列在你的devDependencies中。