直到超时的测试,诺言的测试才得以解决

时间:2019-03-31 11:23:23

标签: javascript promise sinon chai

我们有一个简单的等待方法,可以在节点应用程序中利用promise

exports.wait = (timeout) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve()
    }, timeout)
  });
};

我们试图使用sinon和chai来测试这种行为。

我们设法使用chai-as-promise获得了正确的断言,但它仅检查了promise的解决方式,而不能让我们测试实际行为:

  • 将100毫秒的值传递给wait方法时
  • 我们希望诺言不能在99毫秒后解决
  • 我们希望承诺能在100毫秒内解决

promise与计时器的结合确实让我们头疼。

这是我们最后的尝试设置:

const chai = require('chai');
const expect = chai.expect;
const sinon = require('sinon');
chai.use(require('sinon-chai'));
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);

const wait = require('./wait').wait;

var clock;

before(() => {
  clock = sinon.useFakeTimers();
});

after(() => {
  clock.restore();
})

it('should not resolve until given time', (done) => {
  const promise = wait(100);
  let fulfilled = false;

  promise.then(() => {
    fulfilled = true;
    done();
  });

  clock.tick(99);
  expect(fulfilled).to.be.false;
  clock.tick(2);
  expect(fulfilled).to.be.true;
});

但是fulfilled从未翻转为真,或者至少我们无法阅读。

  

AssertionError:预期为true

然后如何在chain-sinon下将计时器与承诺测试混合使用,以正确分配我们的定时解决方案?

1 个答案:

答案 0 :(得分:1)

您可以从以下问题中测试代码:

const chai = require('chai');
const expect = chai.expect;
const sinon = require('sinon');

const wait = require('./wait').wait;

var clock;

before(() => {
  clock = sinon.useFakeTimers();
});

after(() => {
  clock.restore();
})

it('should not resolve until given time', async () => {  // <= async
  const promise = wait(100);
  let fulfilled = false;

  promise.then(() => {
    fulfilled = true;
    done();
  });

  clock.tick(99);
  await Promise.resolve();  // let any pending Promise callbacks run
  expect(fulfilled).to.be.false;  // Success!
  clock.tick(2);
  await Promise.resolve();  // let any pending Promise callbacks run
  expect(fulfilled).to.be.true;  // Success!
});

详细信息

Fake timers将按setTimeout安排的回调转换为同步调用。

另一方面,

Promise回调在Promise解析时在PromiseJobs queue中排队,并且直到当前执行的消息完成后才运行< / em>。

在这种情况下,当前正在运行的消息是 test ,因此将then设置为fulfilled的{​​{1}}回调直到 之后,测试完成。

您可以使用true测试功能并在要暂停当前运行的消息并允许任何排队的async回调运行的任何时间调用await Promise.resolve();

有关将假计时器与Promise一起使用的其他详细信息,请参见this answer,它使用Promises,但是概念相同。