Should I test that?

Should I test React Native apps?

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

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 the decision changes
WhenDecisionWhy
The app ships JavaScript fixes over the air, such as with EAS Update, and the change touches no native codeTest minimally: one component test per main flow, plus a regression test for each bug that reaches usersReversibility falls to with-effort, because a fix reaches users at their next launch without store review
The app sells subscriptions or in-app purchasesTest mandatory: assert the access granted for each product ID, for a restored purchase and for a receipt that arrives twiceBlast 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 mockTest minimally: one end-to-end test with Detox or Maestro on a simulator for the flow that calls the moduleTest 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 ownsTest 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 dropsTest 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 saveDo not test the screen; let TypeScript check the props and look at it on both platforms before mergingDetectability 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

  1. 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.
  2. 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.
  3. 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' });
});

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.