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

使用Jest FakeTimers测试React进度条Wrapper组件时,进度值断言失败问题求助

Jest FakeTimers测试React进度条Wrapper组件时,进度值断言失败问题求助

我帮你分析一下问题所在,主要有几个关键点需要调整:

1. Fake Timers 启用时机错误

你现在是先渲染组件,再调用jest.useFakeTimers(),但组件挂载时的useEffect会立即调用真实的setInterval,这时候Fake Timers还没接管定时器,后续的jest.advanceTimersByTime根本不会触发定时器回调。必须先启用Fake Timers,再渲染组件。

另外你之前的解构赋值写法也有问题(const _ = {asFragment, getByText} = ...),会导致外部变量无法正确获取渲染结果。修正后的beforeEach代码如下:

describe('Wrapper Tests', () => {
  let asFragment;
  let getByText;

  beforeEach(() => {
    // 先启用Fake Timers,再渲染组件
    jest.useFakeTimers();
    const rendered = getRenderResult(mockProps);
    asFragment = rendered.asFragment;
    getByText = rendered.getByText;
  });

  // ... 其他测试代码
});

2. 需要等待React完成状态更新与重渲染

setProgressPercentage是异步操作,当你调用jest.advanceTimersByTime触发定时器回调后,React需要时间完成状态更新和重新渲染,直接断言会拿到初始的旧值(0)。你需要用waitFor或者act来确保组件更新完成。

方案一:使用waitFor(推荐,符合Testing Library的最佳实践)

import {render, screen, cleanup, waitFor} from '@testing-library/react';

// ...

it('should update the ProgressBar correctly', async () => {
  jest.advanceTimersByTime(INCREMENT * 5);
  // 等待React完成更新,断言最后一次调用的props
  await waitFor(() => {
    expect(ProgressBar).toHaveBeenLastCalledWith(
      expect.objectContaining({ now: 25 }),
      expect.anything() // 忽略React传递的其他参数(比如context)
    );
  });
});

方案二:使用act包裹定时器操作

import { act } from 'react-dom/test-utils';

// ...

it('should update the ProgressBar correctly', () => {
  act(() => {
    jest.advanceTimersByTime(INCREMENT * 5);
  });
  expect(ProgressBar).toHaveBeenLastCalledWith(
    expect.objectContaining({ now: 25 }),
    expect.anything()
  );
});

3. 断言时使用toHaveBeenLastCalledWith

每次状态更新,ProgressBar都会被重新渲染,mock函数会被调用多次(初始调用now=0,之后每次定时器触发都会调用一次)。用toHaveBeenLastCalledWith才能断言最后一次的正确props值,而toHaveBeenCalledWith只会检查是否曾经被调用过该参数,会匹配到初始的0值导致断言失败。

调整这几个点之后,你的测试应该就能正常通过了。

备注:内容来源于stack exchange,提问作者Adrian Bartholomew

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 14:25:28