测试承诺直到超时sinon chai才解决

问题描述 投票:2回答:1

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

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

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

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

  • 将100 ms的值传递给wait方法时
  • 我们希望承诺不会在99毫秒解决
  • 我们期望承诺在100毫秒解决

承诺与计时器的结合确实让我们感到头疼。

这是我们最后一次尝试设置:

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:预期false为真

然后如何将计时器与在chai-sinon下进行的承诺测试相结合,以便恰当地为我们的时间决定提供资

javascript promise sinon chai
1个回答
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 timerssetTimeout安排的回调转为同步通话。

另一方面,当Promise解析时,PromiseJobs queue回调在Promise中排队,并且在当前执行消息完成之后才运行。

在这种情况下,当前运行的消息是测试,因此将then设置为fulfilledtrue回调直到测试完成后才会运行。

您可以使用async测试函数并在要暂停当前正在运行的消息的任何位置调用await Promise.resolve();,并允许运行任何排队的Promise回调。

有关使用Promises的假定时器的其他详细信息,请参阅使用this answerJest,但概念是相同的。

© www.soinside.com 2019 - 2024. All rights reserved.