我可以绕过 Jest 中的所有 setTimeouts 吗?

Can I bypass all setTimeouts in Jest?

我意识到我的测试套件是带有 setTimeouts 的 运行ning 代码。就目前而言,如果我使用 useFakeTimers,我的测试套件就会中断。我现在无法通过所有测试来一次解决每个问题。我希望通过立即 运行 像这样调用他们的回调来绕过所有超时:

jest
  .spyOn(global, 'setTimeout')
  .mockImplementation((callback) => callback());

TS 告诉我 This expression is not callable. No constituent of type 'TimerHandler' is callable.

我也试过这样破解它:

// in beforeEach
jest.spyOn(global, 'setTimeout');

// in test
const callback = mocked(global.setTimeout).mock.calls[0][0] as Function;
callback();

我相当确定我过去曾做过这样的事情,以确保任何 setTimeout 回调立即 运行 而不是等待。我怎样才能做到这一点?我知道这不是最好的主意,但我现在时间有限。

您永远不应该这样做,但从技术上讲,setTimeout 可以获取将得到 eval 的字符串。我假设 TimerHandler 类型涵盖了这个用例。所以这些类型不会让你假设回调总是一个函数。

您应该能够通过仔细检查回调是否是一个函数来修复它:

jest
  .spyOn(global, 'setTimeout')
  .mockImplementation((callback) => typeof callback === 'function' ? callback() : null);

在我自己的环境中使用它,我顺利通过了这个测试:

describe('foo', () => {
  it('foo', () => {
    jest
      .spyOn(global, 'setTimeout')
      .mockImplementation((callback) => (typeof callback === 'function' ? callback() : null))
    let foo = 0
    setTimeout(() => (foo = 123), 100000)
    expect(foo).toEqual(123)
  })
})