#javascript #unit-testing #mocha.js #sinon
#javascript #модульное тестирование #mocha.js #sinon
Вопрос:
Я безуспешно пытаюсь протестировать следующий «рабочий» метод в классе, поскольку это «бесконечный цикл» / рекурсивный:
Class TheClassYaDaYaDa {
constructor(var1) {
(...)
}
async worker() {
return new Promise(async (resolve, reject) => {
try {
await this.doStuff();
return resolve();
} catch (err) {
return reject(err);
} finally {
this.worker();
}
});
}
}
И это тест, который я создаю:
it('It should not throw error', async function () {
let error = false;
const var1 = 'parameterTest';
stub1 = sinon.stub(TheClassYaDaYaDa.prototype, 'doStuff').resolves();
// if I use the following stub logically the test will not succeed. If I don't I get an infinte loop
// stub2 = sinon.stub(TheClassYaDaYaDa.prototype, 'worker').resolves();
let classToTest;
try {
classToTest = new TheClassYaDaYaDa(limitedInstance);
result = await classToTest.worker();
} catch (err) {
error = err;
}
expect(error).to.be.false;
sinon.assert.calledOnce(stub1);
//also assert that the finally statement run at least once!
});
Есть ли способ протестировать этот сценарий?
Ответ №1:
Я бы подошел к этому с другой стороны, рекурсия всегда сложна, но один из популярных проектов — разделить логику планирования и выполнения на две части.
Рассмотрим следующее:
async worker() {
await this.scheduleWorker();
}
private scheduleWorker() {
// return new Promise ...
}
Теперь можно проверить, что функция scheduleWorker вызывает worker, а также что worker вызывает scheduleWorker (если доступны частные методы).
Если нет, вы можете издеваться над методом worker, чтобы возвращать рабочую логику только при первом вызове и noops при последующих вызовах. Это также будет работать для вашего текущего дизайна, позволяя вам утверждать, что рекурсивный вызов был правильно запущен.
Я не очень хорошо разбираюсь в sinon, но вы хотите что-то похожее на:
var originalWorker = classToTest.originalWorker;
classToTest.originalWorker = function() {
originalWorker();
classToTest.originalWorker = function() { }
}
Большинство макетных фреймворков имеют аналогичные элементы управления для многократного включения методов макета (для последующих вызовов).