最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Map paths for Node modules, for unit testing - Stack Overflow

programmeradmin0浏览0评论

Client side I stub out paths to modules with SystemJS, like this

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

and so require('root-ponents/foo'); would map to applicationRoot/rootComponents/foo.

The problem is, if I run a module with require('root-ponents/foo'); in Mocha, Node has no clue what that path means. Is there a sane way to acplish this path mapping in Node?

Is Proxyquire capable of this? I read through their docs but found nothing to indicate it was.

This is just for unit testing, so I'm happy with any solution using any sort of their party utility.

Client side I stub out paths to modules with SystemJS, like this

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

and so require('root-ponents/foo'); would map to applicationRoot/rootComponents/foo.

The problem is, if I run a module with require('root-ponents/foo'); in Mocha, Node has no clue what that path means. Is there a sane way to acplish this path mapping in Node?

Is Proxyquire capable of this? I read through their docs but found nothing to indicate it was.

This is just for unit testing, so I'm happy with any solution using any sort of their party utility.

Share Improve this question asked Jun 2, 2016 at 15:17 Adam RackisAdam Rackis 83.4k57 gold badges278 silver badges400 bronze badges 4
  • 1 Have you seen this discussion? gist.github./branneman/8048520. I believe there are a few solutions/hacks mentioned that would be relevant to what you are trying to do . – user2263572 Commented Jun 10, 2016 at 14:40
  • 1 Why would you use a different module load mechanism for tests ? Why not use SystemJs there too ? – s.d Commented Jun 14, 2016 at 11:24
  • SystemJS is for loading things in the browser. Mocha runs in Node. – Adam Rackis Commented Jun 14, 2016 at 15:08
  • @AdamRackis mocha tests can be run in the browser with karma-mocha – eenagy Commented Jun 15, 2016 at 14:48
Add a ment  | 

3 Answers 3

Reset to default 6 +250

If your only requirement is so simple you can make a utility function that overrides require.

The new require applies a mapping to the path argument, looks for a module in the new path, and you can optionally fallback for modules that do not exist in the mapped path. The code should look like this

const oldRequire = require;
require = (path) => {
    try {
        const mapped = oldRequire(path.replace('root-ponents/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);
    }
};

Option 1 - Modify NODE_PATH(not remended):

Modify NODE_PATH to include the module path in the shell prior to launching node.js.

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

This is not a great option because it requires a pre-launch step and -- since the NODE_PATH contains many paths -- it's not always clear where the module is being loaded from and there's the possibility of name collisions.

Option 2 - Move the module into an external repo

Lets say you move the ponents into a separate 'rootponents' repo available on your GitHub profile.

Then you can install it directly via:

npm install --save github:arackaf/rootponents

Then you should be able to map the project source to a System.js alias.

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

From there it should work as you expected:

require('root-ponents/foo');

Option 3 - Load the module via relative path:

The config.map option is only for mapping external dependencies to aliases.

One simple alternative is to provide a relative path. Relatives paths are based on the baseURL.

For instance, If you're attempting to load:

src/rootComponents/foo.js

The require would be:

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

Note: This all assumes that the require() statements are following System.js patterns/rules.

One other possible option is to provide a System.paths[] option that creates an alias to a local path. I can't verify how/whether this'll work (ie I have never tried it) but the specifics can be found here

You could do module aliasing a lot of different ways as described in this gist, but the simpler way is just to set the starting root path with NODE_PATH, and go from there:

Here's what it looks like with the NODE_PATH environment variable:

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

Then in all your files, no matter where they are in the hierarchy, will resolve from the ./src directory. This eliminates the need for aliases like you describe, but I realize that in your case, may require moving/renaming many files.

Example: require('root-ponents/foo'); => ./src/root-ponents/foo.js

发布评论

评论列表(0)

  1. 暂无评论