如何在sinon中测试超时后是否重复调用该方法

时间:2019-03-21 18:10:39

标签: javascript timeout mocha sinon

我有一个方法启动,它在setTimeout之后调用自己。它检查是否有记录,然后在找不到记录的情况下调整超时。我想在sinon中测试它是否反复调用。

这就是代码的作用,这是一个监听记录是否处于活动状态的过程。 fetchAndMarkRecordAsActive方法从数据库中获取一条记录,然后重复该方法本身,如果找不到记录,它将超时更改为一个小时左右的较长超时。但是,如果记录仍在提取,则超时默认保持为10分钟左右。

ProcessReader.prototype.start = function () {
    const self = this;

    this.fetchAndMarkRecordAsActive(function (error) {
        if (error === 'NO_RECORD_FOUND') {
            self.timeout = self.longTimeout;
        }

        setTimeout(function () {
            self.start();
        }, self.timeout);
    });
}

我应该如何使用sinon进行测试?

这是我要实现的以下测试用例:

  • 它应该在超时后自动调用
  • 如果找到记录,应重复调用

感谢您的帮助。

更新:

this.longTimeout更改为self.longTimeout。我的错误

1 个答案:

答案 0 :(得分:1)

这应该使您入门:

const sinon = require('sinon');

describe('ProcessReader', () => {

  let startSpy;
  let fetchStub;
  let clock;

  beforeEach(() => {
    startSpy = sinon.spy(ProcessReader.prototype, 'start');
    fetchStub = sinon.stub(ProcessReader.prototype, 'fetchAndMarkRecordAsActive');
    clock = sinon.useFakeTimers();
  });

  afterEach(() => {
    startSpy.restore();
    fetchStub.restore();
    clock.restore();
  });

  it('should work as expected', () => {
    const reader = new ProcessReader();

    fetchStub.yields();  // simulate records returned
    reader.start();
    sinon.assert.callCount(startSpy, 1);   // 1
    sinon.assert.callCount(fetchStub, 1);  // 1
    clock.tick(300000);  // wait half the timeout
    sinon.assert.callCount(startSpy, 1);   // still 1
    sinon.assert.callCount(fetchStub, 1);  // still 1
    clock.tick(300000);  // wait the other half
    sinon.assert.callCount(startSpy, 2);   // 2
    sinon.assert.callCount(fetchStub, 2);  // 2
    clock.tick(600000);  // wait the timeout
    sinon.assert.callCount(startSpy, 3);   // 3
    sinon.assert.callCount(fetchStub, 3);  // 3
    fetchStub.yields('NO_RECORD_FOUND');  // now simulate end of records
    clock.tick(600000);  // wait the timeout
    sinon.assert.callCount(startSpy, 4);   // 4
    sinon.assert.callCount(fetchStub, 4);  // 4
    clock.tick(600000);  // wait the timeout
    sinon.assert.callCount(startSpy, 4);   // still 4
    sinon.assert.callCount(fetchStub, 4);  // still 4
    clock.tick(3000000); // wait the rest of longTimeout
    sinon.assert.callCount(startSpy, 5);   // 5
    sinon.assert.callCount(fetchStub, 5);  // 5
    clock.tick(3600000); // wait longTimeout
    sinon.assert.callCount(startSpy, 6);   // 6
    sinon.assert.callCount(fetchStub, 6);  // 6
  });

});

请注意,您还应该使用self访问longTimeout


作为参考,这是我用来创建上述测试的代码:

const ProcessReader = function () {
  this.longTimeout = 3600000;
  this.timeout = 600000;
}

ProcessReader.prototype.fetchAndMarkRecordAsActive = function () { }

ProcessReader.prototype.start = function () {
  const self = this;

  this.fetchAndMarkRecordAsActive(function (error) {
    if (error === 'NO_RECORD_FOUND') {
      self.timeout = self.longTimeout;  // <= use self.longTimeout
    }

    setTimeout(function () {
      self.start();
    }, self.timeout);
  });
}