My React App Unit-Testing Strategies

Harden up your code base with a solid set of unit tests

Emily Xiong
Dec 1, 2020 · 6 min read
A collection of bicycles
A collection of bicycles
Photo by Berto Macario on Unsplash

Unit testing is critical for development, no matter how small the app is. This article blog will go through how I wrote unit tests for an example app.

It’ll explain some of my unit-testing strategies for different parts of a React app:

  • Services
  • Presentational components
  • Smart/container/connected components
  • Redux files
  • Hooks
A pencil writing on a piece of paper with the word “Unit” at the top of the page and the React logo at the bottom.
A pencil writing on a piece of paper with the word “Unit” at the top of the page and the React logo at the bottom.
Unit-testing strategies for a React app

Tech Stack

Here’s a list of the libraries I used:

ESLint Plugins

Adding linting will help developers avoid some mistakes when writing unit tests. To install the ESLint plugins lint-plugin-testing-library and eslint-plugin-jest-dom, enter the following commands:

In the file .eslintrc, add the rules you need. For example, add recommended rules in extends:

Unit Tests for Accessibility

Unit tests could audit accessibility as well, we could use the library jest-axe:

To set it up, create a file called jest.setup.js at the root with the following content:

Specify this file as a setup file in your Jest configuration file (jest.config.js or jest.config.ts):

Below is a unit test to check for accessibility violations for a React component:

Unit test for accessibility

Mock Imports

Sometimes we can’t set up a library or a service for testing, but we can always mock it. It’ll have granular control over what got returned from this library or service.

Example: react-i18next

As an example, I used the library react-i18next, and I have this import in my component:import { useTranslation } from ‘react-i18next’;. However, I don’t really need to set it up for testing — I could just mock it:

In my unit tests, I simply need to import this mock file into the jest.setup.js file.

As an example, I got a function service called countriesService. I need to mock this service in my unit test. Below is how this service file looks like:

countries.service.ts

This is how I mock it in my unit-test file:

Services

As an example, for countriesService I use fetch to make network requests:

countries.service.ts

To test this file, I need to mock up the fetch function. To do so, I install the library jest-fetch-mock:

To set it up, add these lines to jest.setup.js:

In the unit-test file to mock the successful fetch call, type:

To mock the failed fetch call, type:

Here’s the actual unit-test file for the above service:

countries.service.spec.ts

Presentational Components

Presentational components display data only depending on the props passed in from their parents — they’re not connected to any state.

In my opinion, for presentational components, I don’t need to check whether props passed in are displayed accordingly. Most of the time, I just have a unit test for an accessibility check.

Smart/Container/Connected Components

Smart/container/connected components are connected to the state. In my case, I use Redux for state management. Instead of setting up the real Redux store, I also mock it using the library redux-mock-store:

To set up the mock store:

Here are the tests I usually write:

  • Pass in different types of store states and see whether data is displayed correctly:
  • Check whether the dispatch is triggered with the correct action when a certain event happens

Here’s an example of an actual unit-test file I wrote for a smart component:

Redux Files

Note: In the following examples, for the Redux files to be tested, I use Redux Toolkit and redux-observable.

Reducers are pure functions that are simple to test, usually following this pattern:

Here’s an example of a unit test for a reducer:

Unit test file for a reducer

Similar to reducers, selectors are pure functions, usually follow this pattern:

Here’s an example of a unit-test file for selectors:

Unit-test file for a selector

I use redux-observable as middleware to handle async actions. There are definitely other ways, such as Thunk or redux-saga.

In this example, the unit test follows this pattern:

Here’s an example of a unit-test file for an epic:

Hooks

To test custom React hooks, we need to use the library @testing-library/react-hooks:

I used hooks from another library inside my custom hook:

For my unit test, this is how I mock it:

Here’s an example of my custom hook and its unit test:

Coverage Threshold

Now that I’ve written a few unit tests, I need to set a coverage threshold. In my jest.config file, I added these lines:

In the terminal, it should output the coverage report:

Image for post
Image for post
Unit test–coverage report in terminal

In my opinion, for an app, there’s no need to try to reach a super high coverage number. The higher the number might not mean the better the code. I just added some numbers here as a reminder to keep writing meaningful unit tests.

Nevertheless, I also need to set up a precommit hook to ensure unit tests are run and passed before each commit.

  • Install husky
  • In your package.json, add the following lines:

Conclusion

Thanks for reading all the way to the end. Here are the testing strategies that I used for one of my React applications. It might not fit every project’s needs.

Sometimes, more unit tests don’t mean better code. I’ve seen some unit tests that were fragile and constantly breaking. A unit test should be small enough to test just one file and shouldn’t become an integration test. Good unit tests are easy to maintain and read and also serve as good documentation of the code.

Happy testing.

Better Programming

Advice for programmers.

Sign up for The Best of Better Programming

By Better Programming

A weekly newsletter sent every Friday with the best articles we published that week. Code tutorials, advice, career opportunities, and more! Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Emily Xiong

Written by

A frontend web developer in Toronto

Better Programming

Advice for programmers.

Emily Xiong

Written by

A frontend web developer in Toronto

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store