August 19, 2019

Testing React with Enzyme

by Camilo Reyes

Testing React with Enzyme

One great benefit in React is its virtual DOM. React components can render in-memory without the DOM.

For testing, this opens ways to assert components without automating a browser. A unit test is one where there is no need to push a browser. The test is isolated to where it can run without the browser’s DOM. Feedback increases because the tests run faster and are less brittle. This empowers developers to solve one problem at a time when working with React.

In this take, we’ll dive into testing React components with Enzyme. We’ll build a tree hierarchy of components and show simple ways to test. There will be two components, a parent and a child. The parent will loop through a count prop and create as many children as necessary.

Below is the child component:

export const ChildComponent = ({name}) => <p>Hello from {name}</p>;

And, this is the parent component that loops through a prop childrenCount:

const ParentComponent = ({name, childrenCount}) => {
 let children = [];

 for (let i = 1; i <= childrenCount; i++) {
   children.push(<ChildComponent key={i} name={"Child" + i} />);
 }

 return <>
   <h2>{name}</h2>
   {children}
 </>;
};

We’ll use these components to write unit tests in Enzyme. To begin testing, feel free to follow this guide on shallow rendering. It has everything you need to install Enzyme in a typical React app.

With Enzyme installed, import the shallow renderer:

import { shallow } from 'enzyme';

Shallow Renderer

Enzyme’s shallow renderer allows rendering components only one level deep. This isolates tests and adds focus. A single change deep in the hierarchy can affect tests in the entire suite. A better approach is to focus on one level at a time and separate concerns. This creates a one-to-one relationship between unit tests and the React component. Think of each level as the system under test. Code changes in the tree hierarchy should only affect unit tests in a single level.

Before using the shallow renderer, create an object of initial props:

const initialProps = { name: 'Parent', childrenCount: 1 };

These initialPros can be reused on each unit test. This allows the test code to stay DRY, so it doesn’t repeat itself. With this, shallow render the parent component:

const component = shallow(<ParentComponent {...initialProps} />);

An ES6 spread operator sets initial props in the parent component. Inspecting what Enzyme sees shows the following result. Note that it is only rendering one level deep:

<Fragment>
 <h2>
   Parent
 </h2>
 <ChildComponent name="Child1" />
</Fragment>

Protect your React App with Jscrambler

Child Components

Testing child components in a tree can be cumbersome when you have too many children. Enzyme can find child components in the following ways:

  • Component constructor
  • Component display name

Using a component constructor allows Enzyme to pluck a child component in this way:

const element = component.find(ChildComponent);

This works well when there are one or two children. This also means doing an import on each child component. When the system under test has too many children, this scales rather poorly. This imports modules at lower levels which defeats the point of the shallow renderer. It makes tests brittle and increases the number of dependencies.

A better approach is to use the component display name, for example:

const element = component.find('ChildComponent');

Note the child component gets wrapped around in quotes. Enzyme gets this and plucks the child component without importing a single module. The shallow renderer grabs a hold of the child component and its props. This allows basic assertions without going into implementation details.

Enzyme API

Enzyme is like jQuery for React components because it has a feature-rich API. The API makes working with React components a lot easier. It can find, count, and access props in child components.

The following are useful:

  • debug: gives a sneak peek into what Enzyme sees
  • find: pluck components from the tree hierarchy using the component’s name
  • at: if there are many matching components, an index parameter picks one
  • length: check how many children components match
  • prop: pass in the name of the prop to check its value
  • name: the name of the matching component

To see all these in action, re-render the parent component using the shallow renderer:

const component = shallow(<ParentComponent {...initialProps}
 childrenCount={2} />);

Note that even though we set the initial props through a spread, it is still possible to override props on the right. This adds more flexibility, so it doesn’t repeat itself.

With the parent component rendered, use the Enzyme API:

console.log(component.debug());

const element = component.find('ChildComponent');
const child1 = element.at(0);
const child2 = element.at(1);

expect(element.length).toBe(2);
expect(child1.name()).toBe('ChildComponent');
expect(child1.prop('name')).toBe('Child1');
expect(child2.name()).toBe('ChildComponent');
expect(child2.prop('name')).toBe('Child2');

There are many more available in the Enzyme API. But these are the ones we find most useful for testing React components.

CSS selectors are allowed when finding child components. With the shallow renderer, most components can be plucked via the component name. Because Enzyme can render one level deep, tests are unlikely to deal with raw HTML. The at function checks for the order of child components in a tree. This picks the component given where it shows up in the component hierarchy. The prop function can peek inside a prop value. It can only do basic checks because of the shallow renderer. The length property counts how many matching components there are in the hierarchy.

Conclusion

Enzyme’s shallow renderer adds focus and robustness to tests. Shallow rendering is only one level deep, so it isolates tests. It can pluck child components via the component name instead of the constructor. This reduces dependencies and imports in the test code. Enzyme comes with a feature-rich API. Finding, counting, and checking props is possible via the Enzyme API.

Enzyme is the tool of choice for testing React components. The shallow renderer by itself has enough to start writing unit tests.

Lastly, don't forget that if you're building React applications with sensitive logic, you should always protect them against abuse, tampering and reverse-engineering by following our guide.