You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MUI-X v5 DesktopDatePicker时Jest.useFakeTimers超时如何解决

Jest useFakeTimers 导致 MUI-X v5 DesktopDatePicker 测试超时的解决方案

核心原因

MUI-X v5 的 DesktopDatePicker 组件内部依赖 setTimeout、requestAnimationFrame 处理面板切换动画、日期禁用态校验、日历视图渲染的异步逻辑。默认调用 jest.useFakeTimers() 会全量 mock 所有时间相关 API,把组件内部等待执行的异步定时任务全部挂起,任务一直无法执行完成就会导致测试超时。
你本身的需求只是固定 new Date() 返回值来规避跨月选日期、禁用过去日期的逻辑异常,不需要全量 mock 所有时间API,这是触发问题的核心诱因。


可落地的解决方法

按优先级从高到低排列:

  • 只mock Date对象,保留其他时间API的真实实现
    这是最适配你需求的方案,不需要改动组件代码,也不会破坏组件内部的定时逻辑。Jest 27及以上版本支持指定fake timers的mock范围:

    beforeEach(() => {
      jest.useFakeTimers({
        // 保留定时器、动画帧相关API的真实实现,不做mock
        doNotFake: [
          'setTimeout',
          'clearTimeout',
          'setInterval',
          'clearInterval',
          'requestAnimationFrame',
          'cancelAnimationFrame'
        ],
        // 直接在这里指定你要固定的系统时间即可
        now: new Date('2024-05-20T00:00:00.000Z')
      })
    })
    
    afterEach(() => {
      // 每个用例执行完恢复真实时间,避免污染其他测试
      jest.useRealTimers()
    })
    
  • 全量fake timers场景下手动flush待执行任务
    如果你确实需要全量mock时间API(比如测试时间等待相关逻辑),可以在每一步交互触发后手动推进定时器,把组件挂起的任务执行完:

    test('跨月选择非过去日期正常生效', async () => {
      jest.useFakeTimers()
      // 固定系统时间
      jest.setSystemTime(new Date('2024-05-20'))
      render(<DesktopDatePicker disablePast />)
    
      // 打开日期面板
      fireEvent.click(screen.getByRole('textbox'))
      // 执行所有待处理的定时任务,等待面板渲染完成
      jest.runOnlyPendingTimers()
    
      // 点击切换到下个月
      fireEvent.click(screen.getByLabelText('下个月'))
      jest.runOnlyPendingTimers()
    
      // 选择目标日期
      fireEvent.click(screen.getByText('15'))
      jest.runOnlyPendingTimers()
    
      // 写你的断言逻辑即可
      expect(screen.getByRole('textbox')).toHaveValue('06/15/2024')
    
      jest.useRealTimers()
    })
    
  • 测试环境关闭组件动画
    组件大部分定时逻辑都是为了服务过渡动画,测试环境可以直接关闭动画,从根源消除对定时API的依赖:

    import { createTheme, ThemeProvider } from '@mui/material/styles'
    
    // 测试专用主题,全局关闭日期选择器动画
    const testTheme = createTheme({
      components: {
        MuiPickersCalendar: {
          defaultProps: {
            reduceAnimations: true
          }
        }
      }
    })
    
    // 渲染组件时包裹主题即可
    render(
      <ThemeProvider theme={testTheme}>
        <DesktopDatePicker disablePast />
      </ThemeProvider>
    )
    

注意:不要在测试文件顶层无差别调用jest.useFakeTimers()且不做恢复,会污染其他测试用例的执行环境,引发随机失败。

内容的提问来源于stack exchange,提问作者Nate Thibert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:46:34