Javascript 承诺解析后如何正确测试setTimeout

Javascript 承诺解析后如何正确测试setTimeout,javascript,typescript,testing,jestjs,tdd,Javascript,Typescript,Testing,Jestjs,Tdd,如何正确测试此函数 设置超时 超时后的回调 和递归调用 导出函数initScheduler(超时:number,回调:()=>Promise):void{ 设置超时(()=>{ 回调()。然后(()=>{ initScheduler(超时、回调); }); },超时); } 我试过类似的东西 description('initScheduler',()=>{ 它('应按计划拜访',()=>{ 开玩笑。使用faketimers(); 常数超时:数字=60000; 常量回调:jest.Mock=j

如何正确测试此函数

  • 设置超时
  • 超时后的回调
  • 和递归调用
  • 导出函数initScheduler(超时:number,回调:()=>Promise):void{ 设置超时(()=>{ 回调()。然后(()=>{ initScheduler(超时、回调); }); },超时); } 我试过类似的东西

    description('initScheduler',()=>{
    它('应按计划拜访',()=>{
    开玩笑。使用faketimers();
    常数超时:数字=60000;
    常量回调:jest.Mock=jest.fn().mockResolvedValue(未定义);
    initScheduler(超时、回调);
    expect(setTimeout).toHaveBeenCalledTimes(1);
    expect(setTimeout).toHaveBeenLastCalledWith(expect.any(函数),timeout);
    expect(callback).not.toBeCalled();
    jest.advanceTimersByTime(超时);
    expect(callback).toBeCalled();
    expect(设置超时)。toHaveBeenCalledTimes(2);
    });
    });
    

    但最后一个期望返回1

    不要专注于针对
    setTimeout
    的断言。专注于你的职能部门应该做什么

    describe('', () => {
      jest.useFakeTimers();
      const timeout = 300;
      const callback = jest.fn();
    
      beforeEach(() => {
        jest.clearAllTimers();
        callback
          .mockClear()
          .mockReturnValue(Promise.resolve()); 
      });
    
      it('runs callback only after delay given', () => {
        initScheduler(timeout, callback);
        jest.advanceTimersByTime(timeout - 1);
        expect(callback).not.toHaveBeenCalled();
        jest.advanceTimersByTime(2);
        expect(callback).toHaveBeenCalledTimes(1);
      });
    
      it('reruns scheduler if callback been resolved successfully', async () => {
        initScheduler(timeout, callback);
        expect(callback).not.toHaveBeenCalled();
        jest.advanceTimersByTime(timeout);
        await Promise.resolve();
        jest.advanceTimersByTime(timeout);
        await Promise.resolve();
        jest.advanceTimersByTime(timeout);
        await Promise.resolve();
        expect(callback).toHaveBeenCalledTimes(3);
      });
    
      it('stops scheduler if callback rejected', async () => {
        callback.mockReturnValue(Promise.reject());
        initScheduler(timeout, callback);
        jest.advanceTimersByTime(timeout);
        await Promise.resolve();
        jest.advanceTimersByTime(timeout);
        await Promise.resolve();
        expect(callback).toHaveBeenCalledTimes(1);
      });
    });
    
    一些细节

  • 我很惊讶,但是如果没有
    jest.clearAllTimers()
    ,计时器在
    it()
    之间是不会被清除的。可能,这取决于
    jsdom
    实现或
    jest
    版本,我不知道
  • 没有
    wait Promise.resolve()
    您对
    回调的模拟不运行
    。然后
    部分。实际上,它可能是
    wait,而在这个问题上取笑自己的简单API