Skip to content
  • Home
  • Services
  • Professionals
  • AI Alley
  • Bit Lighthouse
  • Blog
  • Start Now
  • Home
  • Services
  • Professionals
  • AI Alley
  • Bit Lighthouse
  • Blog
  • Start Now
César Ribeiro
on February 10, 2023

Complete Guide to Unit Tests with React

Have you ever gotten yourself into a situation where a small change in the project was worrying because you didn’t know what could be broken?

 Well, I guess everybody passed through this at least once at some point. But what we didn’t know back then, is the existence of our best friend, Unit Tests. Unit Tests is a very important topic, no matter what technology you use.

In this article, I want to dive into unit tests (only unit tests) on React Apps.

What’s unit tests?

Unit tests is a technique where you can test a unit — the smallest piece of code that can be logically isolated in an application. It can be a function, a class method, a subroutine, etc. In our case, we will test functions and React components most of the time.

Why unit testing?

As I said before, unit tests is our best friend. It gives us confidence to make changes and refactors without worrying if our application is still working or not. In addition, it ensures us that our code works properly, avoiding bugs and hours of debugging.

E.g.: There is a Link component that redirects internally to the SPA through to prop, then you add a new prop called href that redirects to external links like youtube.com

How do you ensure the to behavior is working normally, and you didn’t break existent flows? By going screen by screen and testing it? Ask for other develops to check their screens? No! Yyou create a unit test that ensure that every time you click on a Link which has a to prop the navigation you be internally, and create another test for href behavior.

Before we practice, you need to know two important things: Jest and React Testing Library.

 

Jest

Jest is a JavaScript/TypeScript framework for testing, it runs the tests, check coverage, allow mocks and more. Jest is Awesome, if you don’t know yet, you must visit the docs after finishing this article.

React Testing Library

React Testing Library is a library that gives you superpowers to test your React Apps. Jest is framework-agnostic, it doesn’t care about which framework you use, so you need to use React Testing Library to handle react for us and made our life easier.

Let’s practice.

I’ll create a new React project using npx create-react-app unit-tests-tutorial --template typescript, create-react-app uses jest and react-testing-library by default, so we don’t need to do any configuration.

Now, let’s clear the project structure to remove unnecessary files.

New project structure

Testing UI Components

I created a simple button component that receives two props: label and onClick

So, let’s do two simple tests: check if the label is rendered and if onClick callback was called.

I want you to focus on the makeSut(SUT — System Under Test) function, I always use it in my tests, no matter wether it is frontend or backend tests. When you centralize your actor (Button), it’s cleaner and easier to make changes on your tests, also it allows you to focus on the behavior you’re working on.

We have two magic functions from @testing-library/react that we need to learn:

  • The render function will render the component in a container and return some helpers like: getByText, getByTestId, getByRole, debug, unmount and more.
  • The fireEvent will dispatch an Event in the element we pass as argument, there are a lot of events, like: click, change, submit, blur, focus, etc.

These two function are the most important to us, we can fully test a component with them. There is the act function that is important too, but I’ll show it later.

If we run the command yarn test, we will have the following result.

test result

Both tests are passing. We ensured that the two behaviors of our component are working correctly.

Now, let’s create a component a little more complex than a button.

The DropdownList component consumes the Button component and renders a list of elements depending on the state, pretty simple. And that’s how it looks:

Dropdown list component

The nice part here, we added the Button component inside DropdownList, and we don’t need to care if it works, all behavior is properly tested, and we know it will work. Now, let’s check what behavior this component has and test it.

Always focus on behavior instead of line coverage. You can end up covering a line but not a behavior.

  • Check if list is hidden on initial render
  • Check if list is visible after one click on the button
  • Check if button labels are changing
  • Check if all items have been rendered correctly
  • Check if the remove callback is being called with correct values

So, let’s test it.

A few nice things:

  • The container prop return the HTMLElement of the container, so you can find elements and do all DOM manipulation you want, on the 3 first tests we used to find an element and use testing-library to check if is rendered on the DOM.
  • jest.fn function at the last test works as a spy, it knows if the function has been called, how many times was called, which parameters, and much more. It’s really nice to mock a dependency.

Again, we used makeSut function to prepare the actor (DropdownList) and make our test focused on behavior. If we run yarn test again, all tests are passing.

test results

Let’s create the App container that will consume the DropdownList component.

So, we have a component that does a fake api call and update the state to pass to the DropdownList. Let’s add a simple test to check if ul is rendered after clicking on the “Show Data” button.

Let’s run yarn test, and we will have a surprise.

test result with error

Our test is passing, but it’s logging an error. What we can do to fix it? Probably suppress error will work as well, but this time we need to fix the problem. So it happens because we have an asynchronous update of state in our component, so jest run the test and didn’t wait until the fakeApiCall runs and update the state, re-rendering the component.

Remember when I told about the act function? Well, it will save us now, wrapping the asynchronous action inside an act(() => { … }) block code, ensure that the test will wait until everything is done. So, let’s fix our test.

And that’s it, so simple, just adding act ensure that fakeApiCall will run, return data and the setState will re-render our component. Only after that, will the button be clicked. Running yarn test, everything is normal again.

test results

Testing Hooks

You’re probably thinking

Cool, but we are on React 18, we use a lot of hooks, how to test it?

It was kind of boring testing hooks, you needed to wrap the hook in a fake element, simulate the click of a button calling the function you need, and get the result. I hated it and react-testing-library hated it too, so they created a new library to help us, called react-hooks-testing-library

Let’s install it yarn add -D @testing-library/react-hooks

Then, I’ll create the classic useCounter hook just as a simple example:

So, the useCounter hook has one state and two methods, how will I ensure that it’s working correctly?

Well, very simple, we use renderHook function to “render” our hook and return the state and the methods from it.

The render function is very nice, it accepts a provider in case your hook needs something like a context, also you can pass initial values to your hooks. All the values returned as inside a ref called result, renderHook also returns unomunt and rerender functions.

Basically, this is how we can test our hooks.

And that’s it! I hope you have enjoyed the content and learned something.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Come with us!

Do you love technology as we do? Subscribe to our newsletter and receive articles about everything surrounding state of art software engineering.

Popular posts

AWS for non-engineers — Networking

October 18, 2024

DeepEval Insights: Enhancing LLM Evaluation Efforts

May 9, 2024

Tactics for Streamlining Development – From Design Docs to API Integration

March 22, 2024

#14 – Bit Lighthouse – Talk with Nicole Vasquez

November 29, 2023

#13 – Bit Lighthouse – Talk with Andrea Iorio

November 24, 2023

Popular tags

react unit testing
Copyright © 2023 Bitboundaire Corp | All Rights Reserved
299 Alhambra Cir – Suite 403 – Coral Gables, Florida – 33134 – United States
  • Home
  • Services
  • Professionals
  • AI Alley
  • Bit Lighthouse
  • Blog
  • Start Now
  • Home
  • Services
  • Professionals
  • AI Alley
  • Bit Lighthouse
  • Blog
  • Start Now
  • Home
  • Services
  • Professionals
  • AI Alley
  • Bit Lighthouse
  • Blog
  • Start Now
  • Home
  • Services
  • Professionals
  • AI Alley
  • Bit Lighthouse
  • Blog
  • Start Now
Linkedin Twitter Instagram Facebook