In our previous React Native blog post we discussed how unit testing with Jest in React Native, was a really useful and effective way to make sure our code continued to work as we expected. This post however, will explore some of the difficulties we have had with testing in React Native, and how we have managed to overcome them.
At the core of Facebook’s React, and React Native frameworks are the concept of ‘components’.
These components are contained, modular UI elements, often containing logic which controls the state of a particular piece of UI.
As with other parts of your code, it’s important that this logic is tested. However unlike the unit tests we showed previously, we found that testing components in React Native is a much more difficult, frustrating and unrewarding process.
Firstly setting up component tests is an arduous task, because the nature of React Native running natively on mobile devices, means that certain environment dependencies and variables are not available when running tests with Jest or any other test runner.
Because of this, the only way to test your React Native components is by completely mocking the React Native module, this means substituting the real implementation of React Native with “fake” modules, and functions, that don’t require all the variables and dependencies that the real one does.
Doing this manually for every part of React Native is a slow, trial by error process, thankfully a few developers have already done much of the hard work, and have created a completely mocked version of React Native.
Whenever React Native updates (which is very often) new mocks have to be created, and old ones fixed to match the changes, in addition any of your own native modules, or third party ones added to your project, will need to manually mocked.
We’ve found that almost every React Native update has broken our test setup, which is often time consuming and frustrating to fix, especially when we could be building new features. The fragility of this type of setup, as well as the component tests themselves, meant that the tests we wrote were constantly breaking, not from code changes we had made, but from unrelated dependencies not being correctly mocked.
This had a overall negative effect on the perceived importance of our tests and testing in general. We found out that other tests, which ensured important parts of our code base worked correctly would sometimes fail and then go unnoticed in amongst the broken component tests.
In a previous post Tim discussed Redux, and the advantages it has in terms of code structure and the ability to more easily reason about the code we wrote. Additionally Redux also encourages the use of “Dumb components”(Sometimes referred as presentational components) which are components that only contain UI, rather than UI mixed with logic.
There will still be times when some logic exists in components, but by moving the most application critical code out of the components, and into individual functions, we can make sure our most important code is tested.
Facebook does provides a plethora of testing utilities for React js (The web framework) however these are designed with a browser environment in mind, and there are not currently any specific React Native utilities.
Testing could definitely be made easier with the right tools, and hopefully over time as React Native’s popularity increases, testing components will become much more straight forward.
Published on June 22, 2016, last updated on August 7, 2018