Module Overview
Estimated Time: 4 hours | Difficulty: Intermediate | Prerequisites: Core React Native concepts
- Jest configuration for React Native
- Testing components with RNTL
- Mocking native modules
- Testing hooks and context
- Snapshot testing
- Code coverage
Jest Setup
Default Configuration
React Native and Expo projects come with Jest pre-configured:Custom Jest Configuration
ThetransformIgnorePatterns setting below is the single most confusing part of React Native testing setup. By default, Jest does not transform code inside node_modules. But React Native packages ship untranspiled ES modules, so you must explicitly whitelist them. If you see “unexpected token import” errors in your tests, this regex is where to look.
Setup File
React Native Testing Library
React Native Testing Library (RNTL) follows the guiding principle: test the way your users interact with your app, not the implementation details. Instead of checking whethersetState was called or a specific internal state variable changed, you query components by their visible text, accessibility labels, or roles — the same things a real user would see and interact with.
This philosophy means your tests survive refactors. Rewrite a component’s internal logic from useState to useReducer? Your tests still pass because the user-facing behavior did not change.
Install RNTL:
Basic Component Testing
Testing with User Events
Testing Hooks
Custom hooks contain reusable logic, and testing them in isolation (without a wrapping component) ensures they work correctly regardless of which component consumes them.renderHook from RNTL gives you a lightweight way to exercise a hook’s API and verify its outputs.
Custom Hook Testing
Testing Async Hooks
Testing Context
Mocking Native Modules
This is where React Native testing diverges most from web testing. Native modules (camera, location, secure storage, biometrics) do not exist in the Jest test environment. You must provide mock implementations that simulate their behavior. The pattern is consistent: create a file in a__mocks__ directory that matches the module’s import path, and export mock functions that return predictable values.
Common Mocks
Testing with Mocked Modules
Snapshot Testing
Testing Utilities
Custom Render Function
Test Data Factories
Code Coverage
Running Coverage
Coverage Configuration
Choosing the Right Testing Approach
Different parts of your app demand different testing strategies. Spending the same effort on every component leads to either under-tested critical paths or over-tested presentational components.
Decision framework for what to test first:
- Start with business logic and hooks. These are fast to test, stable, and catch the bugs that actually matter (wrong calculations, broken state transitions, malformed API payloads).
- Add behavioral tests for user-interactive components. Forms, modals, and multi-step flows deserve thorough testing because bugs here directly block users.
- Use snapshots only for “golden” components. If a component’s visual output is its contract (e.g., a design system button), a snapshot is appropriate. For everything else, behavioral assertions are more resilient.
- Save E2E tests for critical paths. Login, checkout, and data-destructive flows. These tests are expensive to write and maintain — invest only where a failure in production is catastrophic.
Testing React Query Hooks
Testing components that use React Query requires wrapping them in aQueryClientProvider with specific test configuration. This is a common stumbling point because the default QueryClient retries failed queries (which makes test failures confusing and slow).
Edge Cases in React Native Testing
Testing Animated Components
Components that usereact-native-reanimated require special mock setup. Animations run on a separate thread and do not execute in the Jest environment. The common mistake is trying to assert on animated values — they will always be at their initial state in tests.
Testing Components with Timers
jest.useFakeTimers() can cause subtle issues with React Native’s event loop and async operations. The most common trap: waitFor from RNTL uses real timers internally, so calling jest.advanceTimersByTime() inside a waitFor creates a deadlock.
Testing Platform-Specific Behavior
React Native components often branch onPlatform.OS. To test both branches, you need to mock the Platform module per test, which requires jest.resetModules() because Platform is cached.
Best Practices
Test Behavior, Not Implementation
Focus on what the component does, not how it does it
Use Accessible Queries
Prefer getByRole, getByLabelText over getByTestId
Avoid Testing Implementation Details
Don’t test internal state or private methods
Keep Tests Independent
Each test should be able to run in isolation
Query Priority
Use the most user-centric query first. This ordering ensures your tests break only when user-visible behavior changes, not when you rename a CSS class or restructure a component tree:Coverage Targets That Actually Help
A blanket “80% coverage” mandate is worse than targeted coverage requirements. Here is a more useful breakdown:Next Steps
Module 28: Integration Testing
Learn to test component interactions and navigation flows