React Native Testing Library With Redux

In short

This article guides on conducting integration tests for React Native apps using Redux and React Native Testing Library. It covers testing complexities, store setup, and custom rendering functions. It highlights the importance of mocking API calls and separating testing from implementation details. The article also mentions handling initial state and recommends integration tests for primary scenarios and unit tests for specific logic in reducers.

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 <rte-code>buildStore<rte-code> function, we can write a custom <rte-code>renderWithRedux<rte-code> 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!

FAQ

No items found.
React Galaxy City
Get our newsletter

By subscribing to the newsletter, you give us consent to use your email address to deliver curated content. We will process your email address until you unsubscribe or otherwise object to the processing of your personal data for marketing purposes. You can unsubscribe or exercise other privacy rights at any time. For details, visit our Privacy Policy.

Callstack astronaut
Download our ebook

I agree to receive electronic communications By checking any of the boxes, you give us consent to use your email address for our direct marketing purposes, including the latest tech & biz updates. We will process your email address and names (if you have entered them into the above form) until you withdraw your consent to the processing of your names, or unsubscribe, or otherwise object to the processing of your personal data for marketing purposes. You can unsubscribe or exercise other privacy rights at any time. For details, visit our Privacy Policy.

By pressing the “Download” button, you give us consent to use your email address to send you a copy of the Ultimate Guide to React Native Optimization.