如何根据调用者脚本的路径动态解析nodejs所需模块的路径?

时间:2017-06-22 11:14:39

标签: javascript node.js mocha

我是Javascript编程的新手。目前我正在尝试在包含其他编程语言的现有代码库中编写Javascript文件的测试。结构如下所示。

src/js/path1/path2/path3/path4/path5/
    Rectangle.jsx
    Circle.jsx
test/js/path1/path2/path3/path4/path5/
    RectangleTest.jsx
    CircleTest.jsx

RectangleTest.jsx的内容低于

import Rectangle from './../../../../../../../src/js/path1/path2/path3/path4/path5/Rectangle';

describe('<Rectangle>', () => {
    it('Should show content', () => {
        assert.ok(true);
    });
});

如您所见,我需要将路径设置为非常长的相对路径./../../../../../../../src/js/path1/path2/path3/path4/path5。对于我喜欢下面的内容,这将是非常详尽的。

import Rectangle from './Rectangle';

由于测试文件和测试文件的路径非常相似,因此应该可以计算导入要解析的路径。

有办法吗?

我正在使用mocha作为测试框架。我将示例代码上传到Github(link),以便您可以看到它。

2 个答案:

答案 0 :(得分:0)

您可以使用__dirname全局节点变量,该变量包含当前文件的绝对路径。但是,您必须使用require()而不是import ...,因为导入不支持动态路径。

如果您的绝对路径只包含一个测试名称,则可以使用:

const path = require('path');
const retanglePath = path.join(__dirname.replace('/test/', '/src/'), 'Rectangle'));
const Rectangle = require(rectanglePath).default;

注意:.default适用于使用babel转换的ES6导出。

希望这有帮助。

编辑:这是一个解决方案,它也适用于绝对路径中的其他测试文件夹名称(根据您的需要替换相对路径):

const path = require('path');
const basePath = path.join(__dirname, '../../../../');
const srcPath = __dirname.replace(basePath + 'test', basePath + 'src');
const Rectangle = require(path.join(srcPath, 'Rectangle')).default;

答案 1 :(得分:0)

在研究了nodejs如何解析模块之后,事实证明可以通过覆盖require模块来覆盖module函数行为。

所以我写了一个名为bootstrap.js的文件,其中包含以下代码

let path = require('path');
const BASE_DIR = __dirname;
const SRC_DIR = path.resolve(BASE_DIR + '/../../src/js');
var Module = require('module');
Module.prototype.require = new Proxy(Module.prototype.require, {
    apply(target, thisArg, argumentsList){
        let name = argumentsList[0];
        let isLocal = thisArg.filename.startsWith(BASE_DIR) &&
            name.startsWith('./');
        if (isLocal) {
            let testFileDir = path.dirname(thisArg.filename)
            let testPath = testFileDir.replace(BASE_DIR, '');
            let srcPath = SRC_DIR + testPath;
            let relativePath = path.relative(testFileDir, srcPath);
            argumentsList[0] = relativePath + '/' + name;
        }
        return Reflect.apply(target, thisArg, argumentsList)
    }
});

结构现在就像这样

src/js/path1/path2/path3/path4/path5/
    Rectangle.jsx
    Circle.jsx
test/js/
    bootstrap.js
    path1/path2/path3/path4/path5/
       RectangleTest.jsx
       CircleTest.jsx

要执行测试,我使用下面的语句

nyc mocha --recursive \
    --require test/js/bootstrap.js \
    --compilers js:babel-core/register \
    test/js/**/*.{js,jsx}    

使用上面的代码,我可以检查调用者脚本和被调用模块,看看调用者脚本是否位于test目录中。如果确实如此,它将通过使用相对路径来查看模块是否被调用。

优点是,我们仍然可以使用import语句。

import Rectangle from './Rectangle';

describe('<Rectangle>', () => {
    it('Should show content', () => {
        assert.ok(true);
    });
});

缺点是现在测试文件无法在测试目录中调用相对路径。相对路径现在仅在源路径中解析。但它现在很好。我想知道我们是否可以检查模块是否可以解析。

可以阅读更新的源代码here