Matthias Max
Matthias Max

Reputation: 595

require.main.require works but not inside Mocha test

I have written a global function for requiring certain files of my app/framework:

global.coRequireModel = function(name) {
    // CRASH happens here
    return require.main.require('./api/_co' + name + '/_co' + name + '.model');
}

This module is in /components/coGlobalFunctions.

It is required in my main app app.js like this:

require('./components/coGlobalFunctions');

Then in other modules using "something" from the framework I use:

var baseScheme = coRequireModel('Base');

This works but not in the Mocha tests which give me a "Error: Cannot find module" right before the require.main.require call.

It seems that the test is coming from another source folder. But I thought the require.main.require would take out the aspect of having to relatively linking to modules.

EDIT:

An example test file living in api/user:

var should = require('should');
var app = require('../../app');
var User = require('./user.model');
...

Upvotes: 9

Views: 4642

Answers (3)

DDupont
DDupont

Reputation: 451

This is pretty old, but here is my solution.

I needed a test harness module to be published to a private registry and required by the mocha test suite. I wanted the calling test code to pass the code under test to the harness rather than requiring it directly:

var harness = require('test-harness');
var codeUnderTest = harness('../myCode');  

Inside harness (which was found in the project node_modules directory), I used the following code to make require find the correct file:

        if (!path.isAbsolute(target)) {
            target = path.join(path.dirname(module.parent.paths[0]), target);
        }
        var codeUndertest = require(target);
        ...
        return codeUnderTest;

This relies on the require path resolution that always starts with looking for a node_modules subdirectory relative to the calling file. Couple that with module.parent and you can get access to that search path. Then just remove the trailing node_modules part and concatenate the relative filename.

For other scenarios not using relative paths, this could be accomplished with the options parameter to require:

        var codeUndertest = require(target, {paths: module.parent.paths});
        ...
        return codeUnderTest;

And the two could be combined as well. I used the first form because I was actually using proxyquire which does not offer the paths option.

Upvotes: 0

Emily
Emily

Reputation: 51

Because require.main was not index.html in my node-webkit app when running mocha tests, it threw errors left and right about not being able to resolve modules. Hacky fix in my test-helper.js (required first thing in all tests) fixed it:

var path = require('path')
require.main.require = function (name) {
    // navigate to main directory
    var newPath = path.join(__dirname, '../', name)
    return require(newPath)
}

This feels wrong, though it worked. Is there a better way to fix this? It's like combining some of the above solutions with #7 to get mocha testing working, but modifying main's require just to make everything work when testing feels really wrong.

For other avoid-the-".."-mess solutions, see here: https://gist.github.com/branneman/8048520

Upvotes: 5

JME
JME

Reputation: 3642

require.main points to the module that was run directly from node. So, if you run node app.js, then require.main will point to app.js. If, on the other hand, you ran it using mocha, then require.main will point to mocha. This is likely why your tests are failing.

See the node docs of more details.

Upvotes: 7

Related Questions