sinon-spy在异步回调中不包装方法

sinon spy not wrapping method in asynchronous callback

本文关键字:包装 方法 回调 异步 sinon-spy      更新时间:2023-09-26

sinon.spy(object, method)似乎没有按预期包装我的对象#方法。

(我有一种不安的感觉,我看到了这里和这里描述的相同问题,但我不明白为什么会这样。我在调用sinon.spy(...)之前实例化了我的对象,AFAIK我没有使用任何缓存的对象。)

这是完整的测试文件:

var 
AmbitParser = require('../lib/parsers/ambit-parser'),
expect = require('chai').expect,
sinon = require('sinon');
describe('AmbitParser', function() {
    var ambit_parser = new AmbitParser();
    describe('#extractLineItems()', function() {
        it('calls extractLineItems once', function(done) {
            var spy = sinon.spy(ambit_parser, 'extractLineItems');
            ambit_parser.parseBills(function gotBills(err, bills) {
                expect(ambit_parser.extractLineItems.callCount).to.equal(1); // => expected undefined to equal 1
                expect(spy.callCount).to.equal(1);                           // => expected 0 to equal 1
                done();
            });
            ambit_parser.extractLineItems.restore();
        });                     // calls extractLineItems once
    });                         // #extractLineItems
});                             // AmbitParser

expect(ambit_parser.extractLineItems.callCount).to.equal(1);的调用会导致"预期未定义为等于1",如果我将其更改为expect(spy.callCount).to.equal(1);,则会得到"预期0等于1"。

总之,这让我认为对sinon.spy(...)的调用并没有像预期的那样包装ambit_parser.extractLineItems方法,但我不明白为什么会出现这种情况。

问题是对restore()的调用的位置:它不应该在测试函数的主体中。相反,将其放在after()块中。

实际情况是,restore()方法在测试开始后立即被调用,因此在执行回调时,被监视的方法已经被恢复,因此sinon将报告该方法从未被调用。

以下对原始代码的修改将按预期工作:

describe('AmbitParser', function() {
    var ambit_parser = new AmbitParser();
    describe('#extractLineItems()', function() {
        before(function() {
            sinon.spy(ambit_parser, 'extractLineItems');
        });
        after(function() {
            ambit_parser.extractLineItems.restore();
        });
        it('calls extractLineItems once', function(done) {
            ambit_parser.parseBills(function gotBills(err, bills) {
                expect(ambit_parser.extractLineItems.callCount).to.equal(1);
                done();
            });
        });                     // calls extractLineItems once
    });                         // #extractLineItems
});                             // AmbitParser

这个故事的寓意是:确保只有在任何回调完成后才调用reset()