Verdict
Yes
Yes, test a React Native app: unit tests for its logic and one component test per main screen flow, written with Jest and React Native Testing Library and run in CI on every pull request.
Why
- Blast radiususers
- Change frequencyregularly
- Detectabilitysame-day
- Reversibilitycostly
- Test costmoderate
Yes, test a React Native app with unit and component tests that run in CI. My typical case is a product app on iOS and Android that ships about one release a month and has no over-the-air updates. Blast radius is users, because customers meet every broken screen, and Change frequency is regularly. Detectability is same-day, because crash reports and one-star reviews arrive within a day. Reversibility is costly, because every fix waits for a new build, a store review and each user's update, and Test cost is moderate, because the default template ships Jest with a React Native preset and a component test takes me about an hour, so rule R11 gives Test.
| When | Decision | Why |
|---|---|---|
| The app ships JavaScript fixes over the air, such as with EAS Update, and the change touches no native code | Test minimally: one component test per main flow, plus a regression test for each bug that reaches users | Reversibility falls to with-effort, because a fix reaches users at their next launch without store review |
| The app sells subscriptions or in-app purchases | Test mandatory: assert the access granted for each product ID, for a restored purchase and for a receipt that arrives twice | Blast radius rises to money, and Reversibility stays costly, because a wrong grant ends in refunds or support work for each buyer |
| The logic that breaks lives in a native Swift or Kotlin module, such as Bluetooth pairing, which Jest replaces with a mock | Test minimally: one end-to-end test with Detox or Maestro on a simulator for the flow that calls the module | Test cost rises to heavy, because the test needs a native build and a running simulator |
| A crash appears only on Android device models or OS versions that nobody on the team owns | Test it differently: release in stages on Google Play and in phases on the App Store, alert on the crash-free rate, and halt the rollout when it drops | Test cost rises to prohibitive, because no suite can run on every Android device and OS version |
| A screen only lays out its props, and its author checks it in the iOS and Android simulators after each save | Do not test the screen; let TypeScript check the props and look at it on both platforms before merging | Detectability moves to immediately and Reversibility to trivial, because the mistake never leaves the author's simulator |
What breaks if you don't test
A refactor in shared JavaScript breaks a flow that nobody opens before the release, such as password reset. Customers report it within a day of the store approving the build. The fix needs a new build and a new review, and the broken version stays on every phone whose owner has not updated.
What you lose if you over-test
A Jest snapshot of every screen fails at each style change, and reviewers accept the new snapshot without reading the diff. A test that passes against a mocked native module says nothing about the real module on a phone. An end-to-end suite for every screen adds a native build and a simulator boot to each pull request, and its random timeouts teach the team to rerun red builds.
How to test
- Move logic out of components into plain functions, such as validation and the mapping from notifications to screens, and unit test each one with Jest.
- For each main flow, write one component test with React Native Testing Library: render the screen, press the controls, and assert the text the user sees or the request the screen sends.
- Run both in CI on every pull request, and turn each bug that reaches users into a regression test.
Skip snapshots of every screen and tests for each prop combination. The testing overview lists the tools for each level.
When the answer changes
- The app ships JavaScript fixes with EAS Update: one test per main flow is enough.
- The app sells subscriptions: the purchase path needs mandatory tests.
- The bugs that reach users are crashes on devices you do not own: staged rollouts catch them sooner than a suite.
Real incident + Code example
The notification that opened the wrong screen
On a team chat app I worked on, a refactor turned the notification handler into a switch and dropped the message case, so tapping a new-message notification opened the inbox. TypeScript accepted it, because the default branch returned a valid route. Users reported it the same morning and the fix was one line, but Apple's review took a day, and a week later a third of active users still ran the broken version. We added these tests; the first fails on the broken handler:
import { routeForNotification } from './notifications';
test('a message notification opens its conversation', () => {
expect(routeForNotification({ type: 'message', conversationId: 'c42' }))
.toEqual({ screen: 'Conversation', params: { id: 'c42' } });
});
test('a mention opens the conversation at the message', () => {
expect(
routeForNotification({ type: 'mention', conversationId: 'c42', messageId: 'm7' }),
).toEqual({ screen: 'Conversation', params: { id: 'c42', messageId: 'm7' } });
});
test('an unknown type opens the inbox', () => {
expect(routeForNotification({ type: 'promo' })).toEqual({ screen: 'Inbox' });
});
Related questions
FAQ
- Should you write tests for React Native?
Yes, write unit tests for the logic of a React Native app and one component test per main flow, and run them in CI. A fix that reaches users costs a store review, so a failing test before the release is cheaper.
- Is Jest enough to test a React Native app?
Jest with React Native Testing Library is enough for the logic and screens of a typical React Native app. Jest replaces native modules with mocks, so logic in Swift or Kotlin needs one end-to-end test on a simulator with Detox or Maestro.
- Do over-the-air updates make tests less important?
Yes, over-the-air updates such as EAS Update lower the price of a JavaScript bug, because the fix reaches users at their next launch. One component test per main flow is then enough, while native code changes still need a new build and a store review.