如何强制使用绝对路径来引用 Node.js 模块?

4

我有一个使用CommonJS模块风格的钛项目。然而,代码使用绝对路径,因此在构建时,绝对路径被限制在应用程序目录中。

var foo = require("/lib/module");

我想在命令行上运行一些测试,并使用jasmine-node。然而当测试执行模块时,模块将在其require语句中具有上述绝对路径。
是否有一种方法可以隔离(可能是chroot)节点以将绝对要求路径解析为特定目录?如果有,该如何实现?
-- RepositoryRoot/
   |- app/
   |  \- Resources/
   |     |- app.js  # Has require("/lib/module1.js")
   |     \- lib/
   |        |- module1.js # Has require("/lib/module2.js")
   |        \- module2.js
   \- tests/
      \- module1.spec.js # Has require("../app/Resources/lib/module1")
                         # Or require("/lib/module1")

你可以编写自己的 require 函数,或者干脆不这样做。 - Jacob Groundwater
到目前为止,我尝试使用 proxyquire。它的效果很好,但当被测试的模块存在循环依赖时就会出现问题。我真的想避免改变代码,希望能够不受干扰地运行测试。不幸的是,到目前为止我找到的唯一解决方案是遍历每个源文件并删除前导斜杠,然后将 NODE_PATH 设置为资源目录。这篇博客文章提供了一些见解。 - Sukima
这是你要继承的第三方代码吗?为什么以这种方式编码? - Jacob Groundwater
@JacobGroundwater:是的,它是继承而来的。最初编写时,Titanium并没有打算进行单元测试。现在情况有所改善,但代码仍然是遗留的。我正在尽力做到最好,而不必放弃大部分代码。 - Sukima
1个回答

4
找到解决方案后,我学到了以下内容:确切的答案是你无法这样做。Node将绝对路径视为绝对路径。因此,简短的答案是将我的路径从绝对路径更改为伪绝对(相对)路径。以下是这篇博客文章中的一句引用,可以帮助您理解:

Titanium实现的CommonJS require()缺陷,并且不支持正确的相对路径。当尝试将jasmine-node测试运行程序集成到具有最小复杂目录结构的项目中时,这表示一个主要问题。

问题的一个可能解决方法是在Titanium中不使用相对路径require()(但您可以在通过node运行的jasmine规范中使用它们)。我们需要使用Resources作为根目录的完整路径,而不是相对路径。

这可以通过在运行任何node命令之前设置NODE_PATH环境变量来实现。这样,像`require("module/path")这样的路径将由node titanium解析。

有一些注意事项。有些模块需要绝对路径。在这种情况下,需要proxyquire来模拟绝对路径,只要没有任何循环依赖关系,这将起作用。另外,由于node没有Titanium API,您还必须包含mockti软件包以模拟Titanium API。在spec_helper.js中使用它:

global.Ti = require("mockti");

并且

proxyquire = require("proxyquire");
var myModule = proxyquire("relative/path/to/MyModule", {
    "/absolute/path/to/some/module": require("absolute/path/to/some/module")
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接