首页 > 解决方案 > AssertError:预期调用一次,但调用了 0 次

问题描述

我正在使用 nodejs 和 sinon。

当前,当我运行我的应用程序(即 UpdateTask 类)时,它工作正常,甚至出现错误。

但是,当我开始进行单元测试时,我遇到了以下问题。

AssertError: expected updateBook to be called once but was called 0 times

我不明白为什么它应该被调用 0 次。

我在代码中做错了什么吗?

更新任务类:

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();
    });

标签: node.jsunit-testingsinon

解决方案


问题

tempTable.updateBooksinon.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();
});

推荐阅读