React Testing Library(RTL): Set Up and Best Practices

Noah Peden
3 min readJan 21, 2020

--

I’ll start off with an excerpt from Kent C Dodds’ react-testing-library readme as it sums up the current problem many unit and integration tests present, and how react-testing-library solves them:

The problem

You want to write maintainable tests for your React components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testing codebase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don’t break your tests and slow you and your team down.

This solution

The react-testing-library is a very lightweight solution for testing React components. It provides light utility functions on top of react-dom and react-dom/test-utils, in a way that encourages better testing practices. Its primary guiding principle is:

The more your tests resemble the way your software is used, the more confidence they can give you.

Here’s my TLDR: react-testing-library let’s us write simple yet elegant unit tests and purposefully leaves out methods that would tempt developers into testing implementation details — which the end user does not care about. Remember: ONLY TEST WHAT A USER WOULD DO, DO NOT TEST IMPLEMENTATION DETAILS LIKE STATE CHANGE.

BASIC TESTING STRATEGY:

  1. Test that your props, state, and data are all getting rendered correctly on the DOM using .toBeInTheDocument() or .toExist()
  2. Test that any user interaction with your component renders the correct data change on the DOM using .toBe(), toBeTruthy/Falsy(), toHaveLength(), or .toEqual()
  3. Test any side effects, such as making sure the correct function was called with the correct arguments with .toBeCalledWith(myArguments)
  4. Avoid hardcoding any data and use libraries such as faker or chance to mock out props
  5. Mock out any trivial component that you need to import but don’t need to test in order to speed up tests.

COMPONENT.SPEC.JSX SETUP:

  1. Do your imports and mocks:

2. I like to do a setup function that mimics a beforeEach but is a little more powerful that I can then call in each test:

3. Write your tests testing the markup, the user interaction and the side effects:

Some notes:

  1. You don’t need to do an afterEach(cleanup) within your describe if you do import ‘@testing-library/react/cleanup-after-each’; at the top of your file
  2. The best way to debug your tests is to use the debug() method from React Testing Library. Make sure you deconstruct it out of the setup render, return it, then deconstruct it in the test you need it in. You can then pass any selector or container into it and it’ll console into your terminal.
  3. Always ask yourself if what you’re testing is an implementation detail.
  4. I’ve found that writing my components in separated Controller and View files has helped me expand my coverage A LOT. If one file is responsible for the functions and logic, and one is only a dumb view component that just renders out jsx and props you can unit test everything a lot easier than in a combined file.

--

--

Noah Peden

Senior Software Engineer, Returned Peace Corps Volunteer to Mongolia, expert in React and Frontend landia, dragonborn wizard specializing in FIREBALL.