How to write unit and e2e tests for React Native apps using Jest in an Nx workspace
In my previous blog, I finally finished writing my awesome Nx React Native App. The app is running fine. Can I just commit my changes and call it a wrap?
No. As a disciplined developer, I know that finishing writing application code is only a job half done; the other half is writing tests.
This blog will go through:
- How to write unit tests for React Native components
- How to write e2e tests
Example Repo: https://github.com/xiongemi/studio-ghibli-search-engine
Unit Testing with Nx React Native
To run unit tests, simply run:
nx test <your app or lib>
If you’re using Visual Studio Code, you can use Nx Console to run the test command:
You should see the unit test results in your terminal:
Test Suites: 10 failed, 1 passed, 11 total
Tests: 9 failed, 1 passed, 10 total
Snapshots: 0 total
Time: 9.84 s, estimated 21 s
Ran all test suites.
This is what a starter unit test looks like:
Tech Stack
- Testing framework: jest
- Testing library: @testing-library/react-native
To write a unit test:
In your component, you can add testID
:
<Headline testID='title'>{film.title}</Headline>
Then in the test file, you can use function getByTestId
to query testID
:
const { getByTestId } = render(<your component>);
expect(getByTestId('title')).toHaveTextContent(...);
You can view more queries here: https://callstack.github.io/react-native-testing-library/docs/api-queries.
The first time running the unit tests is unlikely to pass. There are usually a few errors I run into, I either have to fix the code and tests, or I need to mock some library.
Troubleshooting
Error: Jest failed to parse a file
If you are using libraries that contain native code, such as react-native-paper
or @react-navigation/native
, you are likely to run into the below error:
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
To fix this, add that library name to transformIgnorePatterns
in the jest.config.js
.
For example:
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base)',
],
Error: Animated
If you use React Native’s Animated library or you use a material library like react-native-paper
or react-native-elements
, you are likely to get the below warning:
console.warn
Animated:useNativeDriver
is not supported because the native animated module is missing. Falling back to JS-based animation. To resolve this, addRCTAnimation
module to this app, or removeuseNativeDriver
. Make sure to runbundle exec pod install
first. Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md
In the test-setup file under your app or lib, add below mock:
jest.mock(
'../../node_modules/react-native/Libraries/Animated/NativeAnimatedHelper'
);
Error: Is your component inside a screen in a navigator?
If you use @react-navigation
library for navigation, and inside your component, there are hooks from this library like useNavigation
and useRoute
, you are likely to get this error:
Couldn't find a route object. Is your component inside a screen in a navigator?
The easiest way to fix this is to mock the @react-navigation/native
library like below in test-setup file under your app or lib:
Error: Could not find “store”
If your component is a smart component that uses Redux Store, you are going to get this error when testing that component:
Could not find "store" in the context of "Connect(Results)". Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(Results) in connect options
To fix this, you need to wrap your component inside <Provider store={store}>
.
First, you need to install redux-mock-store
:
# npm
npm install redux-mock-store @types/redux-mock-store --save-dev
# yarn
yarn add redux-mock-store @types/redux-mock-store --dev
The test would become:
Example unit test with different store states:
Here are how to write unit tests for React Native components and some common errors you are likely to run into.
Now with all the unit tests in place, you need to write e2e tests.
E2E Testing with Nx React Native
When generating an Nx React Native app, you should see a folder ends with e2e created.
To run the e2e tests against Debug build:
- In one terminal, run
nx start <your app>
- In another terminal, run:
# iOS
nx test-ios <your app-e2e>
# Android
nx test-android <your app-e2e>
If you want to run the e2e test against Release build, run:
# iOS
nx test-ios <your app-e2e> --prod
# Android
nx test-android <your app-e2e> --prod
Tech Stack
Generally, the e2e tests should follow the below pattern:
For example, my app’s starter page looks like this:
Here is my e2e test to check whether it displays the heading:
For my component, I added testID
in order to be queried by e2e tests:
<SafeAreaView testID="search-page">
...
<Headline testID="heading">Studio Ghibli Search Engine</Headline>
For example, my app has a flow that users can search text like totoro
and go to the film details:
The e2e test looks like this:
You can read more about matchers and actions in Detox here: https://wix.github.io/Detox/docs/api/matchers.
Conclusion
Here is how to test Nx React Native apps. With Nx, you do not need to explicitly install any testing library like Jest or Detox. So you can dive right in and focus on writing the tests rather than spending time on setup.
Check out my previous blog about Nx React Native:
https://dev.to/nx/share-code-between-react-web-react-native-mobile-with-nx-12eb
Where to go from here?
- join the community Slack
- follow Nx on Twitter
- learn more about Nx at https://nx.dev
- subscribe to the Nx Youtube channel