I am writing a test for an async
function which performs a series of tasks and at one point waits for 60 seconds before doing some more tasks. I am trying to use sinon.useFakeTimers()
to skip those 60 seconds so that I can test the logic after the delay.
foo.js
module.exports.foo = async f => {
// ... more code ...
await new Promise((resolve, reject) => {
setTimeout(resolve, 60000);
});
// ... more code ...
f();
// ... more code ...
};
test-foo.js
const sinon = require('sinon');
const expect = require('chai').expect;
const { foo } = require('./foo');
describe('Module Foo ', function() {
it('call function after 1 minute', function() {
var clock = sinon.useFakeTimers();
const bar = sinon.stub();
foo(bar);
expect(bar.called).to.be.false;
clock.tick(100000);
expect(bar.called).to.be.true; // this one fails
});
});
I tried putting sinon.useFakeTimers();
in various other places, but the Promise doesn't resolve and the stub I pass into foo
doesn't get called.
Make your test function async
and await
a resolved Promise
after advancing your clock to give the Promise
callback queued by the await
in foo
a chance to run before doing your assertion:
const sinon = require('sinon');
const expect = require('chai').expect;
const { foo } = require('./foo');
describe('Module Foo ', function() {
it('call function after 1 minute', async function() { // <= async test function
var clock = sinon.useFakeTimers();
const bar = sinon.stub();
foo(bar);
expect(bar.called).to.be.false; // Success!
clock.tick(100000);
await Promise.resolve(); // <= give queued Promise callbacks a chance to run
expect(bar.called).to.be.true; // Success!
});
});
For complete details see my answer here which uses Jest
and Jest
timer mocks but the concepts are the same and also apply to Mocha
and Sinon
fake timers.