Testing with Jest & React Native Testing Library
Job-ready apps have tests — Jest checks plain functions, and React Native Testing Library checks that components render and respond to taps.
What you will learn
- Explain why automated tests matter
- Write a unit test with Jest
- Test a component’s render and a button press with RNTL
Why test at all
A test is code that checks your other code does the right thing — automatically. Instead of tapping through the app by hand after every change, you run the tests and they tell you in seconds if anything broke. Serious bootcamps and job descriptions expect this, because tests catch regressions (old features breaking when you add new ones) before users do.
Two tools cover most React Native testing:
- Jest — the test runner and assertion library. It finds your test files, runs them, and lets you state what you expect (e.g. "this should equal 4").
- React Native Testing Library (RNTL) — renders a component in a test environment so you can check what is on screen and simulate taps, the way a user would.
New Expo apps come with the jest-expo preset configured. Add the testing library (one-time):
npx expo install --dev @testing-library/react-nativeNote: Output: (Adds the library for development only. Tests are not shipped in your app.)
A unit test with Jest
Start with the simplest case: a plain function. A unit test checks one small piece in isolation. Jest’s test describes a case, and expect(...).toBe(...) states what should be true. Say we have a helper that adds tax:
// total.js
export function withTax(price) {
return price * 1.18; // add 18% tax
}
// total.test.js
import { withTax } from './total';
test('adds 18% tax to a price', () => {
expect(withTax(100)).toBe(118);
});Note: Output (in the terminal, after running npm test):
PASS total.test.js
✓ adds 18% tax to a price
Jest ran the function with 100, compared the result to 118, and they matched — so the test passes. If someone later broke withTax, this test would fail and tell you.
Testing a component with RNTL
Components need more than a value check — you want to know they render the right text and respond to taps. RNTL’s render draws the component in memory, screen.getByText finds text on it, and fireEvent.press simulates a tap. Here we test a counter:
import { render, screen, fireEvent } from '@testing-library/react-native';
import { useState } from 'react';
import { Text, Button, View } from 'react-native';
function Counter() {
const [n, setN] = useState(0);
return (
<View>
<Text>Count: {n}</Text>
<Button title="Add" onPress={() => setN(n + 1)} />
</View>
);
}
test('increments the count when Add is pressed', () => {
render(<Counter />);
expect(screen.getByText('Count: 0')).toBeTruthy(); // starts at 0
fireEvent.press(screen.getByText('Add')); // tap the button
expect(screen.getByText('Count: 1')).toBeTruthy(); // now 1
});Note: Output: PASS ✓ increments the count when Add is pressed The test rendered Counter, confirmed it showed "Count: 0", simulated tapping "Add", then confirmed it showed "Count: 1" — exactly what a user would experience, but checked automatically.
How a test run works, step by step
When you run npm test, here is what happens, in order:
- Jest finds every file ending in
.test.js(or.test.tsx) in your project. - It runs each
test(...)block one by one. - For component tests, RNTL
renderdraws the component in a fake screen held in memory (no real phone needed). - Your
expect(...)lines andfireEventcalls check the output and simulate user actions. - Each assertion either passes (✓) or fails (✗) with a message showing what was expected versus what it got.
- Jest prints a summary — how many passed and failed — and returns success only if every test passed, which is what a CI pipeline checks before allowing a merge.
Tip: Aim tests at behaviour users care about — "does the right text show", "does the button do the thing" — using getByText and getByRole, rather than testing internal details. Tests written from the user’s point of view break less often when you refactor.
Watch out: Do not chase 100% coverage of every line, especially as a beginner. A handful of meaningful tests on your important logic and key screens is far more valuable than many brittle tests of trivial code.
Q. What does React Native Testing Library add on top of Jest?
✍️ Practice
- Write a Jest test for a
discount(price)function that takes 10% off and checkdiscount(200)is180. - Use RNTL to test a component that shows a greeting and check the greeting text is present.
🏠 Homework
- Add one unit test and one component test to an earlier lesson’s code (e.g. the counter), and run
npm testuntil both pass.