Maybe you've noticed the warning when you run tests on React 19: react-test-renderer is deprecated, and the types package isn't seeing further updates either. That's usually the moment teams start asking whether their mobile and web test setups can finally merge into one approach instead of two. Here's how the pieces fit together so you're not stuck maintaining parallel suites for the same app.
TLDR:
- react-test-renderer is deprecated; React 19 warns on
ReactTestRenderer.create()and the package sees no further updates - React Native Testing Library wraps react-test-renderer with queries that mirror real user taps and scrolls, replacing internal-state checks
- Jest ships as the default runner, but most setups still need
transformIgnorePatterns,setupFiles, andmoduleNameMapperfixes - Selector churn, race conditions, and device fragmentation cause most test breakage, not logic bugs
- The same Jest config and RNTL queries generally cover
react-native-web, though gesture-dependent behavior needs separate tests - Minitap runs as an AI QA employee, testing your app on web, iOS, and Android as black-box visual scenarios, and proposing test updates when the UI changes
What Is React Native Testing And Why It Matters
React native testing spans layers most teams underestimate walking in, and choosing among mobile testing frameworks shapes how those layers get covered: static analysis (TypeScript, ESLint) catches mismatches before a test runs, unit tests isolate a function or hook, integration tests check pieces working together, component tests verify on-screen behavior, and end to end tests drive the real app the way a user would. Each layer catches different bugs, and none substitutes for another.
Testable code stays pure, injects dependencies like network calls and timers, and keeps logic separate from the view layer, so a component that fetches and reshapes data splits into a hook and a view, each tested narrowly on its own.
Unit Testing React Native Components With Jest
Jest ships as the default test runner in React Native projects, with preset: "react-native" wired into package.json. Most setups still need three tweaks: transformIgnorePatterns for untranspiled native modules, setupFiles for polyfills, and moduleNameMapper to stub asset imports like images.
A first test typically mounts a component and mocks a native module with jest.mock, so the test never touches real device APIs. Expo projects use jest-expo instead of react-native as the preset, since Expo modules like expo-constants need their own mocks.
React-Test-Renderer: Current Status And Type Support
react-test-renderer converts a component to a plain JavaScript object tree, skipping the DOM, so it captures props and structure but nothing about how a real device or browser would display it. React Native Testing Library wraps this renderer with queries and interactions that mirror how a user actually taps and scrolls through a screen.
That layering matters because react-test-renderer is deprecated. As of React 19, calling ReactTestRenderer.create() fires a warning, and the package, though still on npm, is no longer maintained. The React team recommends Testing Library and its native counterpart instead. React 18 projects still run without warnings, and @types/react-test-renderer will see no further updates. Migrating to Testing Library queries removes the warning and the maintenance risk.
Testing React Native Components With React Native Testing Library
RNTL installs via npm install --save-dev @testing-library/react-native and follows Kent C. Dodds' principle: tests that resemble real usage give more confidence, so you query by text, role, or accessibility label instead of internal state. It builds on react-test-renderer under the hood, and the RNTL GitHub repository tracks compatibility across React 18 and 19. Matchers like toBeVisible now ship built in, replacing the separate jest-native package. Jest runs the tests, RNTL displays and queries inside it, and neither replaces the other.
Setting Up Tests In Expo And Bare React Native Projects
A bare React Native project scaffolded with the community CLI already wires preset: "react-native" into package.json. But any native module added later, a Firebase SDK, a payments library, a push notification package, still needs its own entry in transformIgnorePatterns. That's because Jest doesn't transpile most of node_modules by default. Expo projects skip most of that setup: installing jest-expo swaps in a preset that mocks calls to modules like expo-constants and expo-font out of the box, so the manual mocking that bare projects handle by hand mostly disappears. The real fork between the two setups is native module access: a bare project can install any native dependency and mock it directly with jest.mock, while a managed Expo workflow limits you to whatever the Expo SDK exposes unless you move to a custom dev client. Teams building through EAS still run the same Jest and RNTL suite locally or in CI before triggering a build, since EAS itself doesn't execute unit tests. Whichever path a project takes, the first test looks the same: render a screen, assert on visible text or role, and mock the one native call that would otherwise reach a real device API (camera, location, or push token).
Writing Integration And Component Tests For React Native Apps
A unit vs integration testing distinction plays out here directly: a unit test checks one function in isolation, a component test displays a screen and checks what's visible, and an integration test wires a form, its validation, and a submit handler into one flow. Most useful React Native tests sit in that upper range, since a tap rarely matters apart from the state it changes.
Weak tests assert on internal state and pass even when nothing actually appears on screen, a common pitfall covered in understanding unit testing. Stronger ones use fireEvent.press and await screen.findByText, confirming what a user actually sees. Mock navigation (useNavigation) and native modules with jest.fn() so tests stay fast and independent of any live network.
End-To-End Testing React Native Apps
End-to-end tests drive the actual app the way a user would, tapping through real screens instead of testing components in isolation. Detox pioneered this for React Native with gray-box synchronization, waiting on native events, animations, and network requests before each interaction so tests don't need arbitrary sleeps. Maestro takes a black-box, YAML-based approach instead: no build step tied to the test binary, and flows read like plain instructions, tapOn, inputText, assertVisible, instead of JavaScript. Appium extends the WebDriver protocol to mobile, useful when a team already runs Selenium-style infrastructure and wants one framework across native, hybrid, and web screens. Each of these still needs someone to author the flow, keep selectors current as screens change, and rerun the suite before every release, which is why E2E maintenance cost tends to outpace unit and component tests. Most teams reserve E2E coverage for the handful of flows, checkout, onboarding, and payment, where a broken step does the most damage if it reaches production.
| Tool | Approach | Flow Syntax | Best Fit |
|---|---|---|---|
| Detox | Gray-box synchronization, waits on native events, animations, and network requests | JavaScript, tied to the test binary build | Teams that want the test runner synchronized with app state instead of using arbitrary sleeps |
| Maestro | Black-box, no build step tied to the test binary | Plain YAML instructions (tapOn, inputText, assertVisible) | Teams that want flows readable without JavaScript |
| Appium | Extends the WebDriver protocol to mobile | WebDriver-style scripts across native, hybrid, and web screens | Teams already running Selenium-style infrastructure that want one framework across platforms |

Why React Native Tests Break And How Teams Reduce Maintenance
Tests break most often at the seams: a testID gets renamed during a refactor, a screen changes layout, or an async wait fires before data actually loads. None of these are logic bugs. They're maintenance debt disguised as failures.
Selector churn is the biggest offender, followed by race conditions (a tap assertion firing before a network call resolves) and device or OS fragmentation across screen sizes and app states, the same failure modes covered in guides on fixing flaky mobile UI tests.
Standard mitigations exist:
- Stable testID conventions enforced in code review
- Retry logic and waitFor helpers instead of fixed timeouts
- Visual regression checks that catch layout drift
None of these eliminate the underlying problem outlined in broader flaky tests engineering guides. They reduce how often it bites, not how much upkeep it demands.
Covering Web Alongside Mobile In React Native Testing
When a component tree runs through react-native-web, the same Jest config and RNTL queries generally still work, since the library targets DOM output either way. What changes is the interaction model: no native gestures, no Pressable touch states, and layout comes from CSS instead of Yoga. A fireEvent.press on web resolves to a click, not a touch sequence, so gesture-dependent behavior needs separate coverage, echoing the blind spots covered by cross browser testing practices.

Most teams extend one suite instead of running two, aligning with broader web application testing practices: a shared file covers logic and the view layer, with .web.test.tsx files reserved for real divergence like breakpoints or Platform.select swaps. Feature parity gaps deserve their own assertion too, since a mocked fallback returning undefined can pass silently, a gap that a well-structured mobile testing pyramid helps catch.
Building A Practical React Native Testing Strategy
A practical strategy starts with mapping your app's flows by risk, not by what's easiest to test. Checkout, authentication, and onboarding earn end-to-end coverage because a broken step there costs the most if it reaches production, while a settings toggle rarely needs more than a unit test. From there, match the test type to the layer it's meant to catch. Static analysis and unit tests run on every commit since they're fast. Integration and component tests run before merge to catch broken flows between pieces. E2E suites run before release since they're the slowest and most maintenance-heavy to keep current. Budget maintenance time explicitly instead of treating it as free: a testID convention enforced in code review and a waitFor helper instead of a fixed timeout prevent most of the selector churn and race conditions that quietly erode trust in a suite over time. Revisit the split as the app grows, since a mix that fit ten screens at launch usually undercounts coverage once the app hits fifty. The flows worth protecting most heavily also change as usage patterns shift.
Learning Resources For React Native Testing
For teams onboarding new engineers, curated resources beat scattered blog posts. Point new hires to:
- Official docs: the React Native testing overview covers static analysis through end-to-end testing, linking out to Jest and RNTL setup guides.
- RNTL docs: the Callstack-maintained React Native Testing Library docs walk through queries, matchers, and patterns with runnable snippets.
- Example repos: GitHub repos with mature
__tests__folders show how real teams structure unit, integration, and end to end suites together, which matters more than any tutorial since structure is where projects drift, and where gaps still let bugs slip through, a pattern covered in mobile E2E testing coverage research.
These resources teach syntax, not the discipline of keeping a suite current as the app changes.
How Minitap Extends React Native QA Across Mobile And Web
Minitap is an AI QA employee that extends this same discipline across both platforms from one system: it builds an understanding of the product from your specs, tickets, documentation, and existing test cases, writes scenarios with acceptance criteria, and runs vision-based, black-box regression on your iOS, Android, and web builds. Where a Jest and RNTL suite covers logic and the view layer, Minitap adds the layer that queries alone tend to miss: gesture-dependent behavior, layout drift after a UI change, and the feature-flag combinations that a mocked fallback can pass through silently. When a component ships through react-native-web, Minitap validates the on-screen experience directly on web the same way it validates the native screen, instead of assuming the shared Jest config carries over cleanly. Every run comes with a video and written findings, so a failure on Android, iOS, or web arrives with evidence attached instead of a bare pass or fail. And because tests run on what is on screen, a renamed testID or a shifted layout does not break them; when expected behavior changes, Minitap proposes a test update and your team reviews only what it cannot settle on its own.
FAQ
How do I keep React Native UI tests from breaking every time the design changes?
Selector churn is the biggest source of test maintenance in react native testing: a renamed testID or a layout tweak breaks assertions even when the underlying logic works fine. Standard mitigations like stable testID conventions and retry logic reduce how often this happens, but they don't remove the upkeep, which is why teams weighing react native automated testing at scale increasingly look at agents like Minitap that test what is on screen and propose test updates instead of selector rewrites.
Is react-test-renderer still worth using now that it's deprecated?
Not for new test suites. React 19 fires a warning when you call ReactTestRenderer.create(), @types/react-test-renderer won't see further updates, and the React team directs teams toward React Testing Library and its native counterpart instead. If you're on React 18, existing tests still run without warnings, but any new component test or react native testing tutorial you follow in 2026 should build on @testing-library/react-native instead of react-test-renderer directly.
React Native Testing Library vs Jest, what's the actual difference?
Jest is the test runner and assertion engine; React Native Testing Library (RNTL) is the query and interaction layer that displays components and lets you find them the way a user would, by text, role, or accessibility label. Neither replaces the other: Jest executes the test file and reports pass/fail, RNTL wraps react-test-renderer under the hood to give you fireEvent.press and findByText, and most jest react native setups (including jest-expo for Expo projects) run both together.
Can I automate mobile app testing without writing or maintaining test scripts?
Mostly, yes. Traditional react native unit testing, component tests, and end-to-end suites all require someone to author and update scripts as the UI changes, which is the maintenance debt most teams eventually hit with Jest, RNTL, or Maestro. Minitap takes script authoring off your team for end-to-end regression: it writes scenarios in plain words, runs them on real mobile and web interfaces, and proposes test updates when the interface changes. Keep your Jest and RNTL suite for logic and components.
What's the fastest way to get regression coverage across both mobile and web from one QA approach?
Extending one React Native Testing Library suite (shared logic and display tests, with .web.test.tsx files only for real divergence) covers a good share of shared code, but it still leaves gesture-dependent behavior, layout drift, and feature-flag combinations under-tested across platforms. Minitap covers this gap directly: it runs the same vision-based, black-box regression across iOS, Android, and web from one system, so a release that touches a shared component gets validated on iOS, Android, and web without your team maintaining parallel test files.
Final Thoughts On React Native Testing Strategy
Every layer covered here, from static analysis to end to end checks, catches something the others miss. But keeping that suite reliable as your screens and flows keep changing is the work that actually costs a team time, and it's the work Minitap takes on: it decides what to test from your product context, runs the scenarios on web and mobile, and proposes updates as your screens change, so your team reviews instead of rewriting scripts. See how it works for your team at minitap.ai.
