我有一个模块,不应使用Node从命令行直接调用该模块。为此,我将主模块检查为indicated in the documentation:

if (require.main === module) {
    console.error('This module cannot be run from the command line.');
} else {
    // Here the module logic...
}

现在,我正在为此模块编写单元测试(如果重要的话,请使用Mocha/Chai),并且我想模拟当从命令行将错误打印到stderr时直接从命令行调用模块的情况。

其余逻辑已经在测试中,但是我无法获得单元测试所涵盖的require.main === module分支。我想像出解决此问题的最干净方法是在模块内部模拟require.main,但我不知道如何执行此操作。我们已经使用proxyquire模拟依赖关系,但是在这种情况下它无济于事。

有什么建议如何处理这个问题?

最佳答案

已经3年了,但是我可以模拟这种情况。
概念:对require.mainmodule之间的比较功能进行 stub /模拟。
对于下面的示例:我使用模块:rewire,sinon,chai,mocha和nyc。
有这个index.js

// File: index.js (original)
if (require.main === module)) {
  console.log('Run directly');
} else {
  console.log('Run NOT directly');
}
我创建了一个包含比较2个输入的函数的帮助器。
// File: helper.js
function runDirectly(a, b) {
  // Suppose:
  // a: require.main
  // b: module
  return (a === b);
}

module.exports = { runDirectly };
我将索引修改为类似这样的内容。
// 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');
}
当我直接从命令行尝试时,它仍然可以正常运行。
$ node index.js
Run directly
$
我创建此规范文件。
// 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');
  });
});
然后,当我运行测试和覆盖率时,这里是结果。
$ 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 |
---------------|---------|----------|---------|---------|-------------------
$
现在index.js具有100%的覆盖率,并且helper.js易于测试。 :)

10-07 19:15
查看更多