我正在使用nodejs和sinon。
当前,当我运行我的应用程序(即UpdateTask类)时,它工作正常,甚至出错。
但是,当我开始进行单元测试时,我遇到了以下问题。
AssertError: expected updateBook to be called once but was called 0 times
我不明白为什么它应该被调用0次,而应该被调用一次。
我的代码有什么错误吗?
UpdateTask类:
function updateInfo() {
let updateCountParams = [];
let updateParams = [];
let idsToUpdateList = null;
tempTable.getBookForUpdateCount(updateCountParams, function (results) {
if (results[0].RECCOUNT > 0) {
tempTable.getBookForUpdate(updateParams, function (results) {
idsToUpdateList = results;
for (var i = 0; i < idsToUpdateList.length; i++) {
let id = idsToUpdateList[i].id;
let param = [];
param.push(id);
let request = api.sendRequest(id);
// Invoke asynchronous call
request
.buffer(true)
.end(function (err, res) {
if (err) {
tempTable.updateBook(param, function (updateBookResult) {
});
return console.error(err.status + " - " + err.message);
}
let data = {
body: res.body,
text: res.text
};
let bkData = data.text;
if (bkData == undefined || bkData == null) {
tempTable.updateBook(param, function (updateBookResult) {
});
return console.error("DATA NOT FOUND".red);
}
//success flow business logic here
...
}); //end asynchronous call
}
});
}
else {
//no record to be processed.
return;
}
});
}
测试案例:
describe('Update Task', () => {
beforeEach(() => {
});
afterEach(() => {
sinon.restore();
});
it('3. API Call - Errror: 404 - Not found', (done) => {
let getTempTableForUpdateCountSpy = sinon.stub(TempTableDao, "getBookForUpdateCount").yields(jsonResult.count.success.result);
let getTempTableForUpdateSpy = sinon.stub(TempTableDao, "getBookForUpdate").yields(jsonResult.single.failure.result);
let getTempTableUpdateSpy = sinon.stub(TempTableDao, "updateBook");
let test = nock('https://test.api.com/id')
.get('/ID125125/')
.reply(404, {
});
updateTask.updateInfo();
sinon.assert.calledOnce(getTempTableForUpdateCountSpy);
sinon.assert.calledOnce(getTempTableForUpdateSpy);
test.interceptors[0].statusCode.should.be.equal(404);
sinon.assert.calledOnce(getTempTableUpdateSpy);
done();
});
答案 0 :(得分:1)
tempTable.updateBook
在sinon.assert.calledOnce(getTempTableUpdateSpy);
运行失败之前尚未运行的回调期间被调用。
在断言之前,请确保调用tempTable.updateBook
的回调有机会运行。
在使用Promise(可以在测试中返回并等待Promise)时,这要容易得多。这种情况比较棘手,因为存在回调并且没有干净的方法返回可以等待的内容。
需要注意的重要一点是,测试将一直保持活动状态,直到超时或调用done
。
在这种情况下,updateBook
似乎是代码中发生的最后一件事情,也是需要测试的最后一件事情。对于这种情况,可以为存根提供一个模拟实现,并断言,然后在该模拟实现中调用done
。
这是一个简化的示例:
import * as sinon from 'sinon';
const tempTable = {
updateBook: () => {}
};
const updateInfo = () => {
setTimeout(() => { tempTable.updateBook(); }, 0); // simulate an asynchronous callback
}
test('updateInfo', (done) => {
const spy = sinon.stub(tempTable, 'updateBook');
spy.callsFake(() => {
sinon.assert.calledOnce(spy); // SUCCESS
done();
});
updateInfo();
});
在您的情况下,您可以执行以下操作:
it('3. API Call - Errror: 404 - Not found', (done) => {
let getTempTableForUpdateCountSpy = sinon.stub(TempTableDao, "getBookForUpdateCount").yields(jsonResult.count.success.result);
let getTempTableForUpdateSpy = sinon.stub(TempTableDao, "getBookForUpdate").yields(jsonResult.single.failure.result);
let getTempTableUpdateSpy = sinon.stub(TempTableDao, "updateBook");
let test = nock('https://test.api.com/id')
.get('/ID125125/')
.reply(404, {
});
getTempTableUpdateSpy.callsFake(() => {
sinon.assert.calledOnce(getTempTableForUpdateCountSpy);
sinon.assert.calledOnce(getTempTableForUpdateSpy);
test.interceptors[0].statusCode.should.be.equal(404);
sinon.assert.calledOnce(getTempTableUpdateSpy);
done();
});
updateTask.updateInfo();
});