我们有一个简单的等待方法,在我们的节点应用程序中利用promises
exports.wait = (timeout) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, timeout)
});
};
我们尝试使用sinon和chai来测试这种行为。
我们设法使用chai-as-promise获得了正确的断言,但它只检查了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:预期false为真
然后如何将计时器与在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
解析时,PromiseJobs queue回调在Promise
中排队,并且在当前执行消息完成之后才运行。
在这种情况下,当前运行的消息是测试,因此将then
设置为fulfilled
的true
回调直到测试完成后才会运行。
您可以使用async
测试函数并在要暂停当前正在运行的消息的任何位置调用await Promise.resolve();
,并允许运行任何排队的Promise
回调。
有关使用Promises
的假定时器的其他详细信息,请参阅使用this answer的Jest
,但概念是相同的。