react19-test-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React 19 Test Migration Patterns

React 19 测试迁移模式

Reference for all test file migrations required by React 19.
React 19要求的所有测试文件迁移参考指南。

Priority Order

优先级顺序

Fix test files in this order; each layer depends on the previous:
  1. act
    import
    fix first, it unblocks everything else
  2. Simulate
    fireEvent
    fix immediately after act
  3. Full react-dom/test-utils cleanup remove remaining imports
  4. StrictMode call counts measure actual, don't guess
  5. Async act wrapping for remaining "not wrapped in act" warnings
  6. Custom render helper verify once per codebase, not per test

请按此顺序修复测试文件,每个步骤依赖上一步的完成:
  1. act
    导入
    :优先修复,它是所有后续操作的前提
  2. Simulate
    fireEvent
    :修复完act后立即处理
  3. 全面清理react-dom/test-utils:移除剩余的相关导入
  4. StrictMode调用计数:实测实际次数,不要预估
  5. 异步act包装:处理剩余的「未被act包裹」警告
  6. 自定义渲染辅助函数:每个代码库验证一次即可,无需逐测试用例验证

1. act() Import Fix

1. act() 导入修复

jsx
// Before  REMOVED in React 19:
import { act } from 'react-dom/test-utils';

// After:
import { act } from 'react';
If mixed with other test-utils imports:
jsx
// Before:
import { act, Simulate, renderIntoDocument } from 'react-dom/test-utils';

// After  split the imports:
import { act } from 'react';
import { fireEvent, render } from '@testing-library/react'; // replaces Simulate + renderIntoDocument

jsx
// Before  REMOVED in React 19:
import { act } from 'react-dom/test-utils';

// After:
import { act } from 'react';
如果同时引入了其他test-utils相关内容:
jsx
// Before:
import { act, Simulate, renderIntoDocument } from 'react-dom/test-utils';

// After  split the imports:
import { act } from 'react';
import { fireEvent, render } from '@testing-library/react'; // replaces Simulate + renderIntoDocument

2. Simulate → fireEvent

2. Simulate 替换为 fireEvent

jsx
// Before  Simulate REMOVED in React 19:
import { Simulate } from 'react-dom/test-utils';
Simulate.click(element);
Simulate.change(input, { target: { value: 'hello' } });
Simulate.submit(form);
Simulate.keyDown(element, { key: 'Enter', keyCode: 13 });

// After:
import { fireEvent } from '@testing-library/react';
fireEvent.click(element);
fireEvent.change(input, { target: { value: 'hello' } });
fireEvent.submit(form);
fireEvent.keyDown(element, { key: 'Enter', keyCode: 13 });

jsx
// Before  Simulate REMOVED in React 19:
import { Simulate } from 'react-dom/test-utils';
Simulate.click(element);
Simulate.change(input, { target: { value: 'hello' } });
Simulate.submit(form);
Simulate.keyDown(element, { key: 'Enter', keyCode: 13 });

// After:
import { fireEvent } from '@testing-library/react';
fireEvent.click(element);
fireEvent.change(input, { target: { value: 'hello' } });
fireEvent.submit(form);
fireEvent.keyDown(element, { key: 'Enter', keyCode: 13 });

3. react-dom/test-utils Full API Map

3. react-dom/test-utils 完整API映射表

Old (react-dom/test-utils)New location
act
import { act } from 'react'
Simulate
fireEvent
from
@testing-library/react
renderIntoDocument
render
from
@testing-library/react
findRenderedDOMComponentWithTag
getByRole
,
getByTestId
from RTL
findRenderedDOMComponentWithClass
getByRole
or
container.querySelector
scryRenderedDOMComponentsWithTag
getAllByRole
from RTL
isElement
,
isCompositeComponent
Remove not needed with RTL
isDOMComponent
Remove

旧API(react-dom/test-utils)新位置
act
import { act } from 'react'
Simulate
fireEvent
from
@testing-library/react
renderIntoDocument
render
from
@testing-library/react
findRenderedDOMComponentWithTag
getByRole
,
getByTestId
from RTL
findRenderedDOMComponentWithClass
getByRole
or
container.querySelector
scryRenderedDOMComponentsWithTag
getAllByRole
from RTL
isElement
,
isCompositeComponent
Remove not needed with RTL
isDOMComponent
Remove

4. StrictMode Call Count Fixes

4. StrictMode调用计数修复

React 19 StrictMode no longer double-invokes
useEffect
in development. Spy assertions counting effect calls must be updated.
Strategy always measure, never guess:
bash
undefined
React 19 StrictMode在开发环境下不再重复调用
useEffect
两次,统计effect调用次数的Spy断言需要更新。
策略:始终实测,绝不预估
bash
undefined

Run the failing test, read the actual count from the error:

Run the failing test, read the actual count from the error:

npm test -- --watchAll=false --testPathPattern="[filename]" --forceExit 2>&1 | grep -E "Expected|Received"

```jsx
// Before (React 18 StrictMode  effects ran twice):
expect(mockFn).toHaveBeenCalledTimes(2);  // 1 call × 2 (strict double-invoke)

// After (React 19 StrictMode  effects run once):
expect(mockFn).toHaveBeenCalledTimes(1);
jsx
// Render-phase calls (component body)  still double-invoked in React 19 StrictMode:
expect(renderSpy).toHaveBeenCalledTimes(2);  // stays at 2 for render body calls
npm test -- --watchAll=false --testPathPattern="[filename]" --forceExit 2>&1 | grep -E "Expected|Received"

```jsx
// Before (React 18 StrictMode  effects ran twice):
expect(mockFn).toHaveBeenCalledTimes(2);  // 1 call × 2 (strict double-invoke)

// After (React 19 StrictMode  effects run once):
expect(mockFn).toHaveBeenCalledTimes(1);
jsx
// Render-phase calls (component body)  still double-invoked in React 19 StrictMode:
expect(renderSpy).toHaveBeenCalledTimes(2);  // stays at 2 for render body calls