我目前正在使用nodejs创建一些实验项目。我用Spring编写了很多Java EE web应用程序,并且很欣赏那里的依赖注入的简单性。
现在我很好奇:如何使用节点进行依赖注入?或者:我甚至需要它吗?有没有替换的概念,因为编程风格不同?
到目前为止,我正在谈论一些简单的事情,比如共享数据库连接对象,但是我还没有找到一个令我满意的解决方案。
发布于 2012-06-04 17:32:20
我还写了一个模块来完成这个任务,它叫做rewire。只需使用npm install rewire
,然后:
var rewire = require("rewire"),
myModule = rewire("./path/to/myModule.js"); // exactly like require()
// Your module will now export a special setter and getter for private variables.
myModule.__set__("myPrivateVar", 123);
myModule.__get__("myPrivateVar"); // = 123
// This allows you to mock almost everything within the module e.g. the fs-module.
// Just pass the variable name as first parameter and your mock as second.
myModule.__set__("fs", {
readFile: function (path, encoding, cb) {
cb(null, "Success!");
}
});
myModule.readSomethingFromFileSystem(function (err, data) {
console.log(data); // = Success!
});
我受到Nathan MacInnes's injectr的启发,但使用了一种不同的方法。我没有使用vm
来评估测试模块,实际上我使用了node自己的require。这样,您的模块的行为就像使用require()
一样(除了您的修改)。此外,还完全支持调试。
发布于 2016-02-08 21:20:14
这是我自己调查过的。我不喜欢引入神奇的依赖utils库,这些库提供了劫持模块导入的机制。取而代之的是,我为我的团队提出了一个“设计指南”,通过在我的模块中引入工厂函数导出,明确地说明可以模拟哪些依赖项。
我在参数和解构方面广泛使用了ES6特性,以避免一些样板,并提供了一种命名的依赖覆盖机制。
下面是一个示例:
import foo from './utils/foo';
import bob from './utils/bob';
// We export a factory which accepts our dependencies.
export const factory = (dependencies = {}) => {
const {
// The 'bob' dependency. We default to the standard 'bob' imp if not provided.
$bob = bob,
// Instead of exposing the whole 'foo' api, we only provide a mechanism
// with which to override the specific part of foo we care about.
$doSomething = foo.doSomething // defaults to standard imp if none provided.
} = dependencies;
return function bar() {
return $bob($doSomething());
}
}
// The default implementation, which would end up using default deps.
export default factory();
下面是它的用法示例
import { factory } from './bar';
const underTest = factory({ $bob: () => 'BOB!' }); // only override bob!
const result = underTest();
对于那些不熟悉ES6语法的人,请原谅它。
发布于 2013-08-07 17:21:59
我最近检查了这个线程,原因与OP相同--我遇到的大多数库都临时重写了require语句。我使用这种方法的成功程度参差不齐,所以我最终使用了以下方法。
在一个快速应用程序的上下文中-我将app.js包装在一个bootstrap.js文件中:
var path = require('path');
var myapp = require('./app.js');
var loader = require('./server/services/loader.js');
// give the loader the root directory
// and an object mapping module names
// to paths relative to that root
loader.init(path.normalize(__dirname), require('./server/config/loader.js'));
myapp.start();
传递给加载器的对象映射如下所示:
// live loader config
module.exports = {
'dataBaseService': '/lib/dataBaseService.js'
}
// test loader config
module.exports = {
'dataBaseService': '/mocks/dataBaseService.js'
'otherService' : {other: 'service'} // takes objects too...
};
然后,不是直接调用require...
var myDatabaseService = loader.load('dataBaseService');
如果加载器中没有别名,那么它将默认为常规要求。这有两个好处:我可以交换任何版本的类,并且它消除了在整个应用程序中使用相对路径名的需要(因此,如果我需要在当前文件之下或之上使用自定义库,我不需要遍历,并且需要根据相同的键缓存模块)。它还允许我在应用程序中的任何位置指定mock,而不是在即时测试套件中。
为了方便起见,我刚刚发布了一个小的npm模块:
https://stackoverflow.com/questions/9250851
复制相似问题