Jest 如何测试 Promise 里面的 setTimeout

新手上路,请多包涵
const delay = (time = 0) => new Promise((resolve) =>     setTimeout(resolve, time));

jest 如何测试这个函数

我现在这样写的,没有通过

it('测试 createContext context.delay 延时是否成功', async () => {
expect.assertions(1);
const context = createContext(api, namespace);
const callback = jest.fn();

// 延时 1000 毫秒
context.delay(1000).then(callback);
jest.advanceTimersByTime(1000);

const asyncTest = async () => {
  expect(callback).toBeCalled();
};

await asyncTest();
});
阅读 7.2k
3 个回答
✓ 已被采纳新手上路,请多包涵

把 async 改成了原生的 setTimeout ,测试通过
猜测是因为 async 是微任务,setTimeout 是宏任务 ,所以用 async 包裹测试代码,promise 里面的 setTimeout 总是后于 async 执行,用宏任务的 setTimeout 包裹测试代码就解决了执行顺序的问题


const Time = setTimeout;

jest.useFakeTimers();

it('测试 createContext context.delay 延时是否成功', (done) => {
const context = createContext(api, namespace);
const callback = jest.fn();

// 延时 1000 毫秒
context.delay(1000).then(callback);

// 这个时候 setTimeout 应该已经执行
expect(setTimeout).toHaveBeenCalledTimes(1);

// 快进 1000 毫秒, 这个时候 callback 应该已经被执行
jest.advanceTimersByTime(1000);

Time(() => {
  expect(callback).toBeCalled();
  done();
});
});

控制台输出:

const delay = (time = 0) => new Promise((resolve) => setTimeout(resolve, time));
delay().then(()=>console.log('delay'));
setTimeout(()=>console.log('setTimeout'));

打印结果为 delay, setTimeout

自己试着修改了一下,也是不行。我觉得换个思路,不要去测试promise,直接测试setTimeout函数吧。实际开发过程中测试覆盖率达到100%,基本也是很困难的

新手上路,请多包涵
it('测试 delay 函数延迟是否成功', async () => {
  const mockCallback = jest.fn();

  setTimeout(mockCallback, 1000);

  expect(mockCallback).not.toHaveBeenCalled(); // Success!

  await delay(1000);

  expect(mockCallback).toHaveBeenCalled(); // Success!
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题