REGISTER

React Native Testing Library with Redux

Maciej Jastrzębski
2020-08-05

blog content

Need help with Performance Optimization? 
hire us
Need help with Super app development
hire us
Need help with React Native?
hire us
Need help with migration to React Native?
hire us
Our React Native EU Conference is back
register nowlearn more

An introduction

Testability of Redux reducers is well known, because of their pure functional nature, however proper testing of middleware like Saga or Thunk is somewhat more complex. Additionally testing all of these parts separately does have two major problems:

  • Each of them might work correctly in separation, but it’s not guaranteed when they are assembled
  • Tests become dependent on implementation details of reducers, sages, etc.

This blog post describes how you can write integration tests for React Native apps with Redux, using React Native Testing Library. The setup described here allows us to test all application parts together, in conditions resembling normal app operation when components are connected to the Redux store with attached middleware.

Read more: In case if you missed it - React Native Testing Library has just merged with Testing Library - read the article to find out more about it.

As part of The React Native Show, we released a podcast fully dedicated to future of React Native Testing Library

Setup

Redux store setup

In order to provide a Redux environment consisting of store and middleware, we first build a function for assembling the store. It's a part of your application code, and you should use this function to build the store used by your app. We are going to use it to create a separate store for each test so that our tests work in isolation and do not interfere with each other.


Custom render function using React Native Testing Library

By using the buildStore function, we can write a custom renderWithRedux function that will render our components inside a Redux Provider so that we can test connected components. We will use React Native Testing Library to achieve that. It provides us with convenient helpers to render our components, interact with them, and assert on their output.


Basic integration tests

Finally, we are able to write our integration tests. As our components render with real store and middleware attached, we need to mock API calls so that the middleware does not call real API.

For simplicity, we mock our API calls directly inside the tests. But for more complex apps you'll likely want to come up with some abstraction around your back-end server responses. This will allow you to decouple your test cases from networking, making them even less prone to rewrites in this area. Read more in the Stop mocking fetch blog post.


The benefit of this approach is that our tests do not contain any reference to our Redux or middleware implementation details. We only mock the API calls, and yet we are able to test the whole LoginScreen component without caring about state management libraries used.

Tests with the initial state

In our tests of LoginScreen component, I assumed that we do not need any initial state in our Redux store. However, frequently our components will assume that some state is present, e.g. home screen for a logged-in user could assume that some basic information about the user is available in the store. You can pass such state in the following way:


Other global dependencies

If you have other dependencies like navigation or internationalization libraries, they should also be included in your custom render function in a manner resembling your <rte-code>App.js<rte-code> setup.


Summary

You can easily setup integration tests for your React Native + Redux application. Integration tests are a great way of automating manual test scenarios, especially for major happy and error paths. They cover almost all pieces involved in the tested screen, without need for separate component, reducer & middleware unit tests. In case you have some edge-case logic in your reducers, unit testing is highly encouraged.

Happy testing!

Author:
Maciej Jastrzębski
React & React Native developer with multiple years of experience building native iOS and Android apps. Passionate about building robust & delightful apps along with writing well-architected and readable code. Loves learning new things. In his free time likes to travel, hike in the mountains & take photographs.
arrow icon
MORE posts from this author

Bundle React Native apps using Webpack features

Discover Re.Pack – a Webpack-based toolkit that allows you to build a React Native app with the full support of the Webpack ecosystem.

learn more

More posts from this category

Ensure your React components perform as intended as your app grows

Discover Reassure - our open-source library that allows you to run performance tests measuring the average rendering time of the in-app components.

business benefits

Performance Optimization

To stay competitive, you need a high-performing app. Improving React Native performance can bring your company many business and tech benefits. To learn more about it, check the page entirely dedicated to React Native Performance Optimization. Discover a real-life example of React Native optimization we performed for Aaqua, a Singaporean platform that enables global users to share their passion through groups.

Bundle React Native apps using Webpack features

Discover Re.Pack – a Webpack-based toolkit that allows you to build a React Native app with the full support of the Webpack ecosystem.

business benefits

Why React Native?

Building an all-in-one platform can bring your company a lot of business and tech benefits like seamless UX experience, global reach, brand growth just to name a few. To learn more about the benefits of using React Native to develop super apps, check out the MoMo case study. Where we helped improve app's performance by migrating architecture to Re.Pack.

stay tuned

Subscribe to our newsletter

You may unsubscribe from these communications at any time. For details see the Privacy Policy.