如何测试被setTimeout包裹的showUpdate方法调用情况?
测试被
setTimeout包裹的showUpdate方法调用问题 我在测试一个被setTimeout包裹的方法时遇到问题,目标是验证showUpdate方法是否以false为参数被调用。
组件代码
const UpdateContainer: FunctionComponent<UpdateProps> = ({ showUpdate, showError, dateOfBirth, }) => { const [isEditable, setIsEditable] = useState<boolean>(true); const [isEditing, setIsEditing] = useState<boolean>(true); const onCancel = async function() { setIsEditable(false); setIsEditing(false); setTimeout(()=> { /* 需要验证此方法是否以false为参数被调用 */ showUpdate(false); },600); }; const initialValues: UpdateValues = { birth_date: dateOfBirth, }; const formik = useFormik({ initialValues: initialValues, }); return ( <Card cancelText={t('cancel')} confirmText={t('confirm')} isEditable={isEditable} isEditing={isEditing} setIsEditable={setIsEditable} setIsEditing={setIsEditing} onCancel={() => onCancel()} > <CardItem body={ <Input disabled id="dateOfBirthUpdate" textTransform="none" type="text" value={moment(new Date(formik.values.birth_date ? formik.values.birth_date : '')).format('ll')} /> } /> </Card> ); }; export default Card;
当前测试代码
it('点击提示框内的取消按钮时将showUpdate设为false', async () => { tree(props) jest.useFakeTimers() act(()=>{ jest.runAllTimers() }) const cancelButton = screen.getByText('common:cancel'); expect(cancelButton).not.toBeNull(); userEvent.click(cancelButton); const toolTipCancel= screen.getByText('common:cancelEditTooltip.cancelButtonText') userEvent.click(toolTipCancel); await expect(props.showUpdate).toBeCalledWith(false) });
问题解决步骤
1. 调整Fake Timers的执行时机
你当前在组件渲染后立刻执行jest.runAllTimers(),但此时setTimeout还未被创建(还未触发onCancel方法)。正确逻辑是:先触发按钮点击生成定时器,再执行定时器回调。
2. 规范act的使用范围
React测试中,状态更新、定时器回调这类副作用操作需要包裹在act中,确保组件渲染和状态同步完成。
3. 修正断言方式
toBeCalledWith是同步断言,无需await;同时要确保props.showUpdate是Jest mock函数(测试前需定义const props = { showUpdate: jest.fn() })。
修改后的测试代码
it('点击提示框内的取消按钮时将showUpdate设为false', () => { // 初始化组件,确保showUpdate是mock函数 const props = { showUpdate: jest.fn() }; tree(props); // 启用Fake Timers jest.useFakeTimers(); // 点击外层取消按钮 const cancelButton = screen.getByText('common:cancel'); userEvent.click(cancelButton); // 点击提示框内的取消按钮,触发onCancel生成定时器 const toolTipCancel = screen.getByText('common:cancelEditTooltip.cancelButtonText'); userEvent.click(toolTipCancel); // 执行所有待处理的定时器回调 act(() => { jest.runAllTimers(); }); // 断言showUpdate被正确调用 expect(props.showUpdate).toHaveBeenCalledWith(false); // 清理Fake Timers,避免影响其他测试 jest.useRealTimers(); });
额外兼容处理
如果Card组件的onCancel存在异步逻辑,可使用waitFor包裹断言确保状态更新完成:
import { waitFor } from '@testing-library/react'; // ... act(() => { jest.runAllTimers(); }); await waitFor(() => { expect(props.showUpdate).toHaveBeenCalledWith(false); });
内容的提问来源于stack exchange,提问作者SilverRetriever
相关产品推荐
相关产品推荐

