Redux Unit Testing: A Step-By-Step Guide


For a front-end developer using JavaScript, one of the most popular libraries is React Js, which can be easily integrated with different frameworks (such as Angular and Vue) and other libraries. Another library that integrates well with React is Redux, which shares similarities with React in its storing state but does not work as a state manager for one of the components; it also serves as a global state manager for all applications.  

Unit testing is an essential part of development, allowing us to recreate different scenarios through our applications or even just a little snippet, as not all functions or actions will need to be tested. For example, if a header with text will never be changed, we do not have to test if the header will work as expected. On the other hand, when we have more functions that can affect and/or change the behavior of the code that is already working, or we receive new code, we should test it to check whether it works as before. 

Fortunately, both React and Redux can be easily tested. This applies to the individual components we create and the store and reducers developed with Redux. We can test actions inside reducers to ensure, for example, that clicking a button calls the correct function and accurately updates the states in the store. 

In this article, we will go step by step, from installing React and Redux to implementing simple unit testing to demonstrate how this can be achieved. 

Requirements 

To be able to work with this document, we will need the following:

  • Node.js
  • React
  • Redux 
  • IDE
  • OS can be any (Windows, MacOS, Linux) 

The first step is to download node.js from the official page at https://nodejs.org/en/download, select the installer for our operating system, and once downloaded, execute it. It's an easy wizard that only needs you to click on NEXT/CONTINUE to finish the installation. 

To test if the Node is correctly installed, open the terminal and write"node --version." If there is no error message, then our program is ready to use. Otherwise, you should try reinstalling Node or checking for a misconfigured route in the environment variables to ensure they are correct and exist. 

The next step is to install React. In the terminal, we will type the next command:  

"npx create-react-app <name of our app>" 

Where '<name of our app>' should be replaced with the name we want for our application. 

When running this command for the first time,  we will need to install the package 'create-react-app' and accept the installation to create the React app. 

Once we create our project, we will need to access its directory and install Redux. To do so, we will execute the command: 

"npm install @reduxjs/toolkit react-redux"

Once installed, we should be able to start creating our app with Redux. 

Examples 

We will create a basic app with a counter to test our React with Redux installation. After that, we will perform unit testing for the Redux reducers.  

Our program needs a store as well as a slice that will function as our reducer and include the corresponding actions. In this example, we will have two different components. The first one will have two buttons that increase or decrease the value of our reducer value; the second component will display the current value of our reducer.  

Our counter reducer will then need two actions, one for adding and another for subtracting from the current value. So, our code will look something like this: 

Screenshot 2023-07-26 at 6.45.39 PM

We need to import 'createSlice' from the Redux toolkit to have all the properties for our reducer. These are the name, its initial value, and the actions that can be executed to modify the value for the reducer.  

In this case, our initial value should be 0, and it will add or subtract 1 from the state value depending on the action.  

We also need to export a constant with the value of the state for the reducer and export the different actions for other components.  

Now that we have our reducer completed, we'll create our store. 

Screenshot 2023-07-26 at 6.46.21 PM

First, we create our rootReducer, where we can add all the reducers. Then, we export the configuration of the store and make it available for all our applications. In this case, we wrapped the content of the index.js file to make it look like the following screenshot: 

Screenshot 2023-07-26 at 6.46.51 PM

Wrapped <App /> with Provider and assigned our store to its value.  

Two other components will be used for the buttons and for displaying the value of our reducer state. When a button is clicked, our first component will update by adding or subtracting 1 from the current value of our counter state. 

Screenshot 2023-07-26 at 6.47.39 PM

Our second component will display the text "display counter {counterValue}" where {counterValue} is the current value for our state.

Screenshot 2023-07-26 at 6.48.27 PMNow, let's move on to unit testing our application. We aim to test not only our two components but also our reducers. To do so, we will create a file for the reducer and test all the actions with the expectation that the results will be true. 

Screenshot 2023-07-26 at 6.49.10 PMIn this example, we will test if our store's initial value is set correctly as zero and that our actions to add and subtract work as expected. For the incrementing (adding), we already know that the default value is 0, and we expect it to be 1 when called. In the case of decrementing (subtracting), instead of using the default value of zero, we can create an initial value to test it under different scenarios. 

For our other components, we need to access the store for testing; otherwise, we will receive an error message asking for the Provider of the store. We can solve this in two different ways: the first one is always to render our components, wrap them with the provider, and call our store so we can import each of the tests, irrespective of whether we use it or not. The other method is to create a util that will do this one single time and render the component in our test file. 

For this example, our util looks like this: 

Screenshot 2023-07-26 at 6.49.46 PM

This util is a function that imports the render function from the React Testing Library and the Provider from React Redux and our store.  

Inside, we create a wrapper function that can receive our components, wrap them with the provider, and provide store data.  

To utilize our util, we simply need to import the "renderWithProviders" function

Screenshot 2023-07-26 at 6.50.20 PM

Instead of importing everything that was used on the util, we only need to import the util. Another benefit is that we can access the value of our different reducers. If we need to test the values that are being updated, for example, in the case of the buttons, we should add or subtract from the current value of our state.  

In the test case for the second component, which displays a text with the current value of our reducer state, we will follow the same approach. However, as an extra step, we should use another example of an initial value in case we need to test something different. 

Screenshot 2023-07-26 at 6.50.56 PM

In our first test, we verified that the text was displayed with the default value, which was 0, and on our second test, we assigned a new value for the state and tested it accordingly.  

Key Takeaways  

  • React with Redux enables us to manage global states across our entire application effectively.
  • Unit testing plays an important part in the development process, as it helps minimize bugs throughout the application. 

Resources 

Redux Writing Tests: https://redux.js.org/usage/writing-tests  

About Encora 

Fast-growing tech companies partner with Encora to outsource product development and drive growth. Contact us to learn more about our software engineering capabilities. 

Share this post

Table of Contents