【问题标题】:Map paths for Node modules, for unit testing节点模块的映射路径,用于单元测试
【发布时间】:2016-10-02 10:15:14
【问题描述】:

客户端我使用 SystemJS 将模块路径存根,如下所示

var systemJsConfig = {
    baseURL: "./",
    defaultJSExtensions: true,
    map: {
        'root-components': 'applicationRoot/rootComponents'
    }
};

所以require('root-components/foo'); 将映射到applicationRoot/rootComponents/foo

问题是,如果我在 Mocha 中运行带有 require('root-components/foo'); 的模块,Node 不知道该路径的含义。有没有一种理智的方法可以在 Node 中完成这种路径映射?

Proxyquire 能做到这一点吗?我通读了他们的文档,但没有发现任何迹象。

这仅用于单元测试,因此我对使用任何类型的派对实用程序的任何解决方案都很满意。

【问题讨论】:

  • 你看过这个讨论吗? gist.github.com/branneman/8048520。我相信提到的一些解决方案/黑客与您正在尝试做的事情相关。
  • 为什么要使用不同的模块加载机制进行测试?为什么不在那里也使用 SystemJs 呢?
  • SystemJS 用于在浏览器中加载内容。 Mocha 在 Node 中运行。
  • @AdamRackis mocha 测试可以在浏览器中运行karma-mocha

标签: javascript node.js mocha.js proxyquire


【解决方案1】:

您可以通过多种不同的方式为模块别名as described in this gist,但更简单的方法是使用NODE_PATH 设置起始根路径,然后从那里开始:

NODE_PATH 环境变量如下所示:

NODE_PATH=./src node src/server/index.js

然后在您的所有文件中,无论它们在层次结构中的哪个位置,都将从./src 目录解析。这消除了对您所描述的别名的需求,但我意识到在您的情况下,可能需要移动/重命名许多文件。

例如:require('root-components/foo'); => ./src/root-components/foo.js

【讨论】:

  • 感谢您提供的好信息 - 看起来该要点中的模式试图解决一个不同的问题,即消除像 ../../../../foo/bar 这样的东西。客户端 JavaScript 加载器简单地提供自定义路径解析。我只是想看看是否有一些技巧可以使这些自定义路径在 Node 中用于单元测试。设置全局 NODE_PATH 对我来说的问题是它会影响加载的 所有内容,而不仅仅是 root-components 中的少数内容
【解决方案2】:

选项 1 - 修改 NODE_PATH(不推荐):

在启动 node.js 之前修改 NODE_PATH 以在 shell 中包含模块路径。

exports NODE_PATH=./path/to/module:$NODE_PATH

这不是一个很好的选择,因为它需要一个预启动步骤,而且 -- 因为 NODE_PATH 包含许多路径 -- 并不总是清楚从哪里加载模块,并且存在名称冲突的可能性。

选项 2 - 将模块移动到外部仓库

假设您将组件移动到您的 GitHub 配置文件中可用的单独“根组件”存储库中。

然后可以直接通过以下方式安装:

npm install --save github:arackaf/rootcomponents

然后您应该能够将项目源映射到 System.js 别名。

var systemJsConfig = {
    baseURL: "./",
    defaultJSExtensions: true,
    map: {
        'root-components': 'github:arackaf/rootcomponents'
    }
};

从那里它应该可以按您的预期工作:

require('root-components/foo');

选项 3 - 通过相对路径加载模块:

config.map 选项仅用于将外部依赖项映射到别名。

一个简单的替代方法是提供相对路径。亲属路径基于 baseURL。

例如,如果您尝试加载:

src/rootComponents/foo.js

要求是:

require('./src/rootComponents/foo')

注意:这一切都假设 require() 语句遵循 System.js 模式/规则。

另一个可能的选项是提供一个System.paths[] 选项,用于创建本地路径的别名。我无法验证这将如何/是否有效(即我从未尝试过),但可以在 here

找到具体信息

【讨论】:

  • 是的,可悲的是,解决方案可能是在我需要在 Mocha 中使用的任何模块中不使用 maped 路径。 叹息
  • @AdamRackis 也许结帐System.config.packagesgithub.com/systemjs/systemjs/blob/master/docs/…。看起来您可以将 commonjs 指定为模块格式并将本地路径映射到别名。
  • 当然,但是将本地路径映射到别名是我的问题的根源 - 当我尝试通过 Mocha 运行这些模块时,Node 不理解这些别名并引发错误。
【解决方案3】:

如果您的唯一要求如此简单,您可以创建一个覆盖require 的实用程序函数。

新的 require 将映射应用于路径参数,在新路径中查找模块,并且您可以选择回退映射路径中不存在的模块。代码应该是这样的

const oldRequire = require;
require = (path) => {
    try {
        const mapped = oldRequire(path.replace('root-components/foo', 'applicationRoot/rootComponents/foo'));
        if (!mapped) {
            throw new Error('module not found in mapped directory');
        }
        console.log('module resolved with mapping', path);
        return mapped;
    } catch (e) {
        console.log('using old require without mapped path', path);
        return oldRequire(path);
    }
};

【讨论】:

  • 我想就是这样!谢谢-不知道为什么我没想到:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
  • 2012-06-25
  • 1970-01-01
  • 2011-01-05
  • 2016-05-15
  • 1970-01-01
相关资源
最近更新 更多