Chapter 10: Testing React Components
High-integrity React testing moves beyond simple unit tests into Integration Testing that simulates real user interactions and validates the Fiber reconciliation state. This chapter specifies the use of the act() utility for state synchronization and the implementation of network-level mocking.
I. The act() Utility & Fiber Synchronization
The act() function is critical for ensuring that all React updates have been processed before assertions are made. Internally, when you wrap code in act(), React flushes all pending work in the Fiber Update Queue. This includes state updates, effect reconciliations, and concurrent transitions. Modern testing libraries like React Testing Library (RTL) wrap their APIs in act() by default, ensuring that your tests assert against the final committed DOM state.
II. Production Anti-Patterns
- Testing Implementation Details: Checking state values instead of the rendered UI. This makes tests brittle during refactors (e.g., changing
useStatetouseReducer). - Missing
act()for Async: Failing to wrap async updates inact(), leading to flaky tests and "stale state" assertions. - Mocking Too Much: Mocking entire child components instead of rendering the full subtree, which fails to verify component integration.
III. Performance Bottlenecks
- Test Execution Latency: Running massive suites sequentially. Use parallel execution (Vitest) to leverage multi-core CPUs.
- Memory Leaks in Tests: Failing to clean up event listeners or MSW handlers, causing test runner crashes during long CI runs.
- JSDOM Layout Gaps: Relying on element dimensions (e.g.,
offsetWidth) which JSDOM does not calculate, leading to false-positive test passes.