Back

How to Migrate Your Tests from Enzyme to React Testing Library

How to Migrate Your Tests from Enzyme to React Testing Library

If your React test suite still depends on Enzyme, you’re maintaining code against a library that stopped receiving official updates years ago. Enzyme has no adapter for React 18 or 19, and unofficial workarounds are unreliable. The path forward is clear: migrate to React Testing Library (RTL).

This article covers the conceptual shifts required for a successful Enzyme to React Testing Library migration, common refactoring patterns, and practical guidance for teams tackling this work in 2025.

Key Takeaways

  • Enzyme lacks official adapters for React 18 and 19, making migration to React Testing Library essential for modern React projects.
  • RTL focuses on testing user-facing behavior rather than implementation details, producing more stable and meaningful tests.
  • Replace Enzyme’s shallow() and mount() with RTL’s render(), and use accessible queries like getByRole() instead of find().
  • Migrate incrementally by running both libraries side by side and converting tests in batches, starting with simpler components.

Why Enzyme Is No Longer Viable

Enzyme was the dominant React testing tool for years. But its tight coupling to React internals became a liability. When React 17 shipped, community adapters filled the gap. React 18 broke that pattern entirely—no official adapter exists, and none has been announced as the Enzyme project is effectively unmaintained.

Beyond compatibility, Enzyme encouraged testing implementation details: checking internal state, calling instance methods, and using shallow rendering to isolate components from their children. These patterns produce brittle tests that break during refactors even when behavior stays the same.

React Testing Library takes the opposite approach. It renders components fully and queries the DOM the way users interact with it—by role, label, and text content. This aligns with modern React testing best practices and produces tests that remain stable through implementation changes.

The Core Philosophy Shift

The biggest challenge in this migration isn’t syntax. It’s mindset.

Enzyme tests often look like this:

  • Access component instance via wrapper.instance()
  • Call setState() or setProps() directly
  • Assert on internal state values
  • Use shallow() to skip child component rendering

None of these have direct RTL equivalents. RTL intentionally omits them because they test things users never see.

Instead, RTL tests focus on:

  • What renders in the DOM
  • How elements respond to user interaction
  • Whether accessible roles and labels are present

To replace Enzyme shallow rendering, you render the full component tree and mock dependencies at the module level when needed. This requires more setup but produces more meaningful coverage.

Common Refactoring Patterns

Replace shallow() and mount() with render()

RTL’s render() function mounts your component into a DOM environment. There’s no shallow equivalent. If child components cause issues, mock them with Jest:

jest.mock('./ChildComponent', () => () => <div data-testid="child-mock" />);

Replace wrapper.find() with Accessible Queries

Enzyme’s find('button') becomes RTL’s screen.getByRole('button'). Prefer queries that reflect how users locate elements:

  • getByRole() for interactive elements
  • getByLabelText() for form inputs
  • getByText() for visible content

Remove instance() and state() Assertions

If you’re testing that clicking a button updates internal state, reframe the test: what does the user see after clicking? Assert on the rendered output instead.

Handle Async Behavior with findBy and waitFor

Enzyme required manual wrapper.update() calls. RTL handles updates automatically. Use findByRole() or waitFor() for async assertions.

Real-World Migration Is Achievable

Large teams have completed this migration successfully. Slack Engineering converted over 15,000 tests using a combination of AST-based codemods and LLM-assisted transformations. The New York Times engineering team described their Enzyme migration as the largest piece of their React 18 upgrade.

The common approach: migrate incrementally. Run both libraries side by side. Convert tests in batches, starting with simpler components. Use automation where syntax changes are mechanical, but expect manual work for tests that relied heavily on implementation details.

React 19 and the Future of Component Testing

React 19 deprecates react-test-renderer for component testing, further consolidating RTL as the standard. If you’re planning a React upgrade, completing your Enzyme to React Testing Library migration first removes a major blocker.

Modern React testing in 2025 means writing tests that survive refactors, validate accessibility, and reflect real user behavior. RTL delivers on all three.

Conclusion

Migrating from Enzyme requires more than find-and-replace. You’re adopting a different testing philosophy—one that prioritizes user-facing behavior over internal implementation. The effort pays off in tests that are more stable, more meaningful, and compatible with current and future React versions.

Start with a small batch. Reframe your assertions around what users see. Let go of shallow rendering. Your test suite will be better for it.

FAQs

Yes. Both libraries can coexist in the same project. This allows you to migrate tests incrementally without disrupting your existing test suite. Install RTL alongside Enzyme, convert tests in batches, and remove Enzyme once migration is complete.

RTL discourages testing internal state directly. Instead, test the observable outcome. If clicking a button changes state, verify what the user sees after the click—such as updated text, a new element appearing, or a changed attribute. This approach produces more resilient tests.

Mock the problematic child component at the module level using Jest. This isolates your test from the child's implementation while still rendering the parent component fully. Use jest.mock to replace the child with a simple placeholder element.

Yes. RTL remains the recommended testing library for React 19. React 19 deprecates react-test-renderer for component testing, making RTL the standard choice. Completing your migration before upgrading to React 19 removes a significant compatibility obstacle.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay