【问题标题】:Node / Mocha / Chai / Sinon - Async await unit test errorNode / Mocha / Chai / Sinon - 异步等待单元测试错误
【发布时间】:2018-02-13 02:24:05
【问题描述】:

我正在尝试异步等待/sinon,但遇到一个奇怪的错误,这就是我所拥有的:

billing.js

exports.getUnbilledChargesSummary = async(function (callback) {
    try {
        var retailerList = await(exports.getBillableRetailerList());
        var chargesList = await(exports.getAllUnbilledChargesSums());
        var result = exports.assignUnbilledChargesSumForEachRetailer(retailerList, chargesList);
        return callback(null, result);
    }
    catch (ex) {
        console.error('Exception in getUnbillecChargesSummary');
        console.error(ex)
        return callback(ex);
    }
});

billing.test.js

describe('billing', () => {
    const retailers = [{ id: 111, common_name: 'Retailer 1' }, { id: 222, common_name: 'Retailer 2' }, { id: 333, common_name: 'Retailer 3' }];
    const charges = [{ retailer_id: 111, sum: 100 }, { retailer_id: 222, sum: 200 }];

    it('should get summary of all unbilled charges for each retailer', (done) => {
        var getBillableRetailerListStub = sinon.stub(billing, 'getBillableRetailerList').returns(Promise.resolve(retailers));
        var getAllUnbilledChargesSumsStub = sinon.stub(billing, 'getAllUnbilledChargesSums').returns(Promise.resolve(charges));

        billing.getUnbilledChargesSummary((err, result) => {
            console.log('result', result);
            expect(result).to.deep.include({ id: 111, common_name: 'Retailer 1', sum: 100 });
            expect(result).to.deep.include({ id: 222, common_name: 'Retailer 2', sum: 200 });
            expect(result).to.deep.include({ id: 333, common_name: 'Retailer 3', sum: 10 });
            done();
        });
    });
});

似乎我的函数中的 catch 正在捕获期望的错误,这是输出:

    billing
result [ { id: 111, common_name: 'Retailer 1', sum: 100 },
  { id: 222, common_name: 'Retailer 2', sum: 200 },
  { id: 333, common_name: 'Retailer 3', sum: 0 } ]
Exception in getUnbillecChargesSummary
{ AssertionError: expected [ Array(3) ] to deep include { id: 333, common_name: 'Retailer 3', sum: 10 }
    at billing.getUnbilledChargesSummary (/Users/User/work/billing_api/services/billing.test.js:19:36)
    at Object.<anonymous> (/Users/User/work/billing_api/services/billing.js:58:16)
    at tryBlock (/Users/User/work/billing_api/node_modules/asyncawait/src/async/fiberManager.js:39:33)
    at runInFiber (/Users/User/work/billing_api/node_modules/asyncawait/src/async/fiberManager.js:26:9)
  message: 'expected [ Array(3) ] to deep include { id: 333, common_name: \'Retailer 3\', sum: 10 }',
  showDiff: false,
  actual:
   [ { id: 111, common_name: 'Retailer 1', sum: 100 },
     { id: 222, common_name: 'Retailer 2', sum: 200 },
     { id: 333, common_name: 'Retailer 3', sum: 0 } ],
  expected: undefined }
result undefined
Unhandled rejection AssertionError: Target cannot be null or undefined.
    at billing.getUnbilledChargesSummary (/Users/User/work/billing_api/services/billing.test.js:17:36)
    at Object.<anonymous> (/Users/User/work/billing_api/services/billing.js:63:16)
    at tryBlock (/Users/User/work/billing_api/node_modules/asyncawait/src/async/fiberManager.js:39:33)
    at runInFiber (/Users/User/work/billing_api/node_modules/asyncawait/src/async/fiberManager.js:26:9)

    1) should get summary of all unblled charges for each retailer
    - should get list of all billable retailers
    - should get sum for each unbilled retailer in retailer bill charges


  0 passing (2s)
  5 pending
  1 failing

  1) billing should get summary of all unbilled charges for each retailer:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

如果我不检查预期的失败(最后一项,retailer3 总和为 10),如果我删除函数中的 catch (无论如何我在实时代码中无法做到),则代码可以正常工作, mocha 似乎仍然没有调用 done()。

【问题讨论】:

  • 为什么要把回调和async/await混在一起?
  • exports.getUnbilledChargesSummary 返回一个承诺,即使通过了回调。
  • 我对 promises 很陌生 :D,如果没有回调,你会如何做到这一点?
  • return result 等等!在调用代码时使用 async/await 或 Promise 链:exports.getUnbilledChargesSummary(...).then(result =&gt; ....)

标签: node.js mocha.js sinon chai


【解决方案1】:

你不应该混合回调和async/awaitexports.getUnbilledChargesSummary返回一个承诺,即使是通过回调。

要在调用函数中获取异步函数的结果,可以使用async/await或promise链:

exports.getUnbilledChargesSummary = async () => {
    try {
        var retailerList = await(exports.getBillableRetailerList());
        var chargesList = await(exports.getAllUnbilledChargesSums());
        return exports.assignUnbilledChargesSumForEachRetailer(retailerList, chargesList);
    } catch (err) {
        console.error('Exception in getUnbillecChargesSummary');
        console.error(err);
        throw err;
    }
};

为了在 Mocha 中测试异步函数,您可能需要调用回调 done 或返回一个 Promise。因为getBillableRetailerListgetAllUnbilledChargesSums 也是异步函数,所以你应该在 sinon.stub 中使用resolves,而不是returns 回调。

describe('billing', () => {
    const retailers = [{ id: 111, common_name: 'Retailer 1' }, { id: 222, common_name: 'Retailer 2' }, { id: 333, common_name: 'Retailer 3' }];
    const charges = [{ retailer_id: 111, sum: 100 }, { retailer_id: 222, sum: 200 }];

    it('should get summary of all unbilled charges for each retailer', async () => {
        let getBillableRetailerListStub = sinon.stub(billing, 'getBillableRetailerList').resolves(retailers);
        let getAllUnbilledChargesSumsStub = sinon.stub(billing, 'getAllUnbilledChargesSums').resolves(charges);

        let result = await billing.getUnbilledChargesSummary();
        expect(result).to.deep.include({ id: 111, common_name: 'Retailer 1', sum: 100 });
        expect(result).to.deep.include({ id: 222, common_name: 'Retailer 2', sum: 200 });
        expect(result).to.deep.include({ id: 333, common_name: 'Retailer 3', sum: 10 });
    });
});

【讨论】:

  • 谢谢,在测试中调用billing.getUnbilledChargesSummary()之前必须加await(..),否则只是过早地测试失败了,这正常吗?
  • 是的,我忘记添加await关键字,修复了答案。
猜你喜欢
  • 2021-10-03
  • 2023-04-11
  • 2020-02-28
  • 2018-11-05
  • 1970-01-01
  • 2019-02-03
  • 2018-09-03
  • 2017-10-23
  • 2021-03-14
相关资源
最近更新 更多