测试承诺直到暂停辛农柴才得到解决
我们有一个简单的等待方法,它利用节点应用程序中的承诺
exports.wait = (timeout) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, timeout)
});
};
我们尝试使用sinon和chai测试此行为。
我们设法使用Chai-as-Promised获得了正确的断言,但它只检查承诺解析,而不能让我们测试真实的行为:
- 将100毫秒的值传递给等待方法时
- 我们预计承诺不会在99ms内解析
- 我们预计承诺在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
永远不会翻转为True,或者至少我们无法阅读它。
AssertionError:False应为True
那么如何在chai-sinon下将计时器与承诺测试混合在一起,以正确评估我们的定时解决方案?
解决方案
您可以从如下问题测试代码:
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中排队,直到当前执行的消息完成后才运行。
在这种情况下,当前运行的消息是the test,因此将fulfilled
设置为true
的then
回调直到测试完成后才会运行。
您可以使用async
测试函数,并在要暂停当前运行的消息并允许运行任何排队的Promise
回调的任何位置调用await Promise.resolve();
。
有关将假计时器与Promises
一起使用的其他详细信息,请参阅this answer,其中使用Jest
,但概念是相同的。
相关文章