节点模块的映射路径,用于单元测试

Map paths for Node modules, for unit testing

客户端我用 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 有这个能力吗?我通读了他们的文档,但没有发现任何迹象。

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

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

下面是 NODE_PATH 环境变量的样子:

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

那么在你的所有文件中,无论它们在层次结构中的什么位置,都将从 ./src 目录中解析。这消除了对您描述的别名的需要,但我意识到在您的情况下,可能需要 moving/renaming 许多文件。

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

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

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

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

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

选项 2 - 将模块移至外部存储库

假设您将组件移动到您的 GitHub 个人资料中可用的单独 'rootcomponents' 存储库中。

然后你可以直接安装它:

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 patterns/rules.

之后

另一种可能的选择是提供一个 System.paths[] 选项来创建本地路径的别名。我无法验证 how/whether 这是否有效(即我从未尝试过)但可以找到具体细节 here

如果您的唯一要求很简单,您可以创建一个实用函数来覆盖 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);
    }
};