【问题标题】:NodeJS and Javascript (requirejs) dependency injectionNodeJS 和 Javascript (requirejs) 依赖注入
【发布时间】:2012-01-11 05:58:35
【问题描述】:

我目前正在使用 requirejs 来管理模块 js/css 依赖项。 我想发现让节点通过集中配置文件执行此操作的可能性。 所以不要手动做类似的事情

define([    
'jquery'
'lib/somelib'
'views/someview']

在每个模块内。

我会让节点注入依赖项,即

require('moduleA').setDeps('jquery','lib/somelib','views/someview')

无论如何,我对任何关注节点依赖注入的项目都很感兴趣。

谢谢

【问题讨论】:

  • 依赖注入不适用于动态语言。
  • @justin - 谢谢,但我不敢苟同。也许这个术语不正确,但我所说的不是动态的吗?
  • 不,动态语言天生就是这样,不需要 DI。 DI 的重点是通过静态类型解决这个限制。
  • "从服务器动态注入需要数据"clux.github.com/modul8
  • 最近的一篇 Javascript has a Built-In Dependency Injection Framework 非常相关:caines.ca/blog/programming/…

标签: javascript node.js dependency-injection express requirejs


【解决方案1】:

我想出了一个依赖注入的解决方案。它被称为injectr,它使用节点的vm 库并在包含文件时替换require 的默认功能。

所以在您的测试中,不要使用require('libToTest'),而是使用injectr('libToTest' { 'libToMock' : myMock });。我想让界面尽可能简单,无需更改正在测试的代码。我觉得效果很好。

值得注意的是,注入器文件是相对于工作目录的,不像 require 是相对于当前文件的,但这无关紧要,因为它只用于测试。

【讨论】:

【解决方案2】:

我之前曾想过提供一个替代 require 以在 Node.js 中提供一种依赖注入形式。

模块代码

例如,假设您在 code.js 中有以下语句: fs = 要求('fs');

console.log(fs.readFileSync('text.txt', 'utf-8'));

如果您使用node code.js 运行此代码,那么它将打印出 text.txt 的内容。

喷油器代码

但是,假设您有一个测试模块想要抽象出文件系统。
您的测试文件 test.js 可能如下所示:

var origRequire = global.require;
global.require = dependencyLookup;
require('./code.js');

function dependencyLookup (file) {
  switch (file) {
    case 'fs': return { readFileSync: function () { return "test contents"; } };
    default: return origRequire(file);
  }
}

如果您现在运行node test.js,它将打印出“测试内容”,即使它包含 code.js

【讨论】:

  • 这仍然对您有用吗?当我尝试这种方法时,我所有的相对路径都会中断。 Error: Cannot find module './lib/model-store.js' 好像所有模块都试图从测试的基目录加载,而不是从被测文件加载。
  • 由于此代码最终使用常规要求,我怀疑这是您这边的路径错误。您能否验证它在没有注入器代码的情况下是否仍然有效?
【解决方案3】:

我还编写了一个模块来实现这一点,它叫做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 来评估测试模块,实际上我使用节点自己的要求。这样,您的模块的行为与使用 require() 完全相同(您的修改除外)。也完全支持调试。

【讨论】:

  • 有趣的方法。我想我在github.com/lukeschafer/modulemock 的实现更像是注入器
  • 虽然我发现 mocking 需要 JS 中的一个通用模式,但我仍然在为声明依赖项与需要文件而不是在构造函数中声明它们并在组合根处解析它们的想法斗争。我在这里打开了一个关于这个确切主题的问题:stackoverflow.com/questions/37836813/…
猜你喜欢
  • 1970-01-01
  • 2013-12-02
  • 2013-06-28
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
相关资源
最近更新 更多