首页 > 解决方案 > 如果方法在超时后被重复调用如何在sinon中测试

问题描述

我有一个在 setTimeout 之后调用自身的方法 start。它检查它是否有记录,如果没有找到记录,则调整超时。如果它反复调用,我想在 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.longTimeoutself.longTimeout。我的错

标签: javascripttimeoutmocha.jssinon

解决方案


这应该让你开始:

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

推荐阅读