I have a module which is not supposed to be called directly from the command line with Node. For this purpose, I'm checking the main module as indicated in the documentation:
if (require.main === module) {
console.error('This module cannot be run from the command line.');
} else {
// Here the module logic...
}
Now I'm writing unit tests for this module (using Mocha/Chai if that matters) and I would like to simulate the case where the module is called directly from the command line, when an error should be printed to stderr.
The rest of the logic is already under test, but I can't get the require.main === module
branch covered by my unit tests. I imaging the cleanest way to solve this would be mocking require.main
inside the module but I have no idea how to do this. We already use proxyquire to mock dependencies but it doesn't help in this situation.
Any suggestions how to deal with this problem?
It has been 3 years, but I able to simulate the condition.
Concept: stub/mock the compare function which compare between require.main
and module
.
For this example below: I use modules: rewire, sinon, chai, mocha, and nyc.
There is this index.js
// File: index.js (original)
if (require.main === module)) {
console.log('Run directly');
} else {
console.log('Run NOT directly');
}
I create helper which contains function to compare 2 input.
// File: helper.js
function runDirectly(a, b) {
// Suppose:
// a: require.main
// b: module
return (a === b);
}
module.exports = { runDirectly };
And I modify the index to something like this.
// File: index.js (modified)
const helper = require('./helper.js');
if (helper.runDirectly(require.main, module)) {
console.log('Run directly');
} else {
console.log('Run NOT directly');
}
When I try directly from command line, It still run correctly.
$ node index.js
Run directly
$
I create this spec file.
// File: index.spec.js
const rewire = require('rewire');
const sinon = require('sinon');
const { expect } = require('chai');
const helper = require('./helper.js');
describe('Index', function () {
let sandbox;
before(function () {
sandbox = sinon.createSandbox();
});
afterEach(function () {
sandbox.restore();
});
it('simulate run directly', function () {
const stubHelperRunDirectly = sandbox.stub(helper, 'runDirectly');
// Simulate require.main === module.
stubHelperRunDirectly.returns(true);
const stubConsoleLog = sandbox.stub(console, 'log');
rewire('./index.js');
expect(stubHelperRunDirectly.calledOnce).to.equal(true);
expect(stubConsoleLog.calledOnce).to.equal(true);
expect(stubConsoleLog.args[0][0]).to.equal('Run directly');
});
it('simulate run NOT directly', function () {
const stubHelperRunDirectly = sandbox.stub(helper, 'runDirectly');
// Simulate: require.main !== module.
stubHelperRunDirectly.returns(false);
const stubConsoleLog = sandbox.stub(console, 'log');
rewire('./index.js');
expect(stubHelperRunDirectly.calledOnce).to.equal(true);
expect(stubConsoleLog.calledOnce).to.equal(true);
expect(stubConsoleLog.args[0][0]).to.equal('Run NOT directly');
});
});
Then when I run test and coverage, here the result.
$ npx nyc mocha index.spec.js
Index
✓ simulate run directly
✓ simulate run NOT directly
2 passing (45ms)
---------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|---------|----------|---------|---------|-------------------
All files | 96.77 | 100 | 83.33 | 96.77 |
helper.js | 50 | 100 | 0 | 50 | 10
index.js | 100 | 100 | 100 | 100 |
index.spec.js | 100 | 100 | 100 | 100 |
---------------|---------|----------|---------|---------|-------------------
$
Now index.js has 100% coverage and helper.js is easy to test. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With