如何用笑话测试承诺延迟?



这是我用来延迟进程的代码(用于退避(

export function promiseDelay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

我想测试它,但我不能。我尝试使用假计时器,但我的测试永远不会结束。

test('promiseDelay delays for 1s', async (done) => {
jest.useFakeTimers();
Promise.resolve().then(() => jest.advanceTimersByTime(100));
await promiseDelay(100);
});

promiseDelay返回一个在ms后解析的Promise,因此在then中调用spy并测试以查看是否在不同的时间间隔后调用了spy

describe('promiseDelay', () => {
beforeEach(() => { jest.useFakeTimers(); });
afterEach(() => { jest.useRealTimers(); });
test('should not resolve until timeout has elapsed', async () => {
const spy = jest.fn();
promiseDelay(100).then(spy);  // <= resolve after 100ms
jest.advanceTimersByTime(20);  // <= advance less than 100ms
await Promise.resolve();  // let any pending callbacks in PromiseJobs run
expect(spy).not.toHaveBeenCalled();  // SUCCESS
jest.advanceTimersByTime(80);  // <= advance the rest of the time
await Promise.resolve();  // let any pending callbacks in PromiseJobs run
expect(spy).toHaveBeenCalled();  // SUCCESS
});
});

请注意,测试代码是同步的,计时器模拟使setTimeout同步,但thenPromiseJobs中排队回调,因此在测试spy是否已调用之前,需要允许任何排队的回调运行。

这可以通过使用asynctest 函数并在已解析的Promise上调用await来完成,该在PromiseJobs结束时有效地对测试的其余部分进行排队,从而允许在测试继续之前运行任何挂起的回调。

有关承诺和假计时器如何交互的其他信息,请参阅我的回答 这里.

我认为您只需要从函数中返回承诺,例如

test('promiseDelay delays for 1s',() => {
jest.useFakeTimers();
return Promise.resolve().then(() => jest.advanceTimersByTime(100));
});

然后监视要调用一次的设置超时。

最新更新