#javascript #node.js #unit-testing #module #mocking
#javascript #node.js #модульное тестирование #модуль #издевательство
Вопрос:
У меня есть модуль, который не должен вызываться непосредственно из командной строки с помощью Node. Для этой цели я проверяю основной модуль, как указано в документации:
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 для подделки зависимостей, но в данной ситуации это не помогает.
Есть предложения, как справиться с этой проблемой?
Комментарии:
1. Почему вам обязательно нужно, чтобы эта строка была закрыта? Эта ветвь предназначена специально для запуска приложения — для тестирования я бы просто запустил приложение и убедился, что оно работает должным образом. 100% покрытие кода — опасная метрика.
Ответ №1:
Прошло 3 года, но я смог смоделировать это условие.
Концепция: заглушка / макет функции сравнения, которая сравнивает между require.main
и module
.
Для этого примера ниже: я использую модули: 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');
});
});
Затем, когда я запускаю test и coverage, вот результат.
$ 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 легко протестировать. 🙂