react19-test-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReact 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:
- import fix first, it unblocks everything else
act - →
Simulatefix immediately after actfireEvent - Full react-dom/test-utils cleanup remove remaining imports
- StrictMode call counts measure actual, don't guess
- Async act wrapping for remaining "not wrapped in act" warnings
- Custom render helper verify once per codebase, not per test
请按此顺序修复测试文件,每个步骤依赖上一步的完成:
- 导入:优先修复,它是所有后续操作的前提
act - →
Simulate:修复完act后立即处理fireEvent - 全面清理react-dom/test-utils:移除剩余的相关导入
- StrictMode调用计数:实测实际次数,不要预估
- 异步act包装:处理剩余的「未被act包裹」警告
- 自定义渲染辅助函数:每个代码库验证一次即可,无需逐测试用例验证
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 + renderIntoDocumentjsx
// 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 + renderIntoDocument2. 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 |
|---|---|
| |
| |
| |
| |
| |
| |
| Remove not needed with RTL |
| Remove |
| 旧API(react-dom/test-utils) | 新位置 |
|---|---|
| |
| |
| |
| |
| |
| |
| Remove not needed with RTL |
| Remove |
4. StrictMode Call Count Fixes
4. StrictMode调用计数修复
React 19 StrictMode no longer double-invokes in development. Spy assertions counting effect calls must be updated.
useEffectStrategy always measure, never guess:
bash
undefinedReact 19 StrictMode在开发环境下不再重复调用两次,统计effect调用次数的Spy断言需要更新。
useEffect策略:始终实测,绝不预估
bash
undefinedRun 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 callsnpm 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