Components are designed to be modular and reusable, which actually makes them great for unit testing! This post assumes you have a moderate understanding of React, but let’s look at an instance of two React classes that interact with each other - a simple
TodoList and some
TodoList is pretty straightforward - it greets the user with a simple
span and then lists as many
Todos as were given to it via its parent (let’s assume the parent of the
Todo is contacting a store or API or whatever to gather exactly what are the todos).
Now, like good developers, let’s establish a test suite to ensure that our
TodoList does exactly what we want it to.
React provides a nice set of test utilities that allow us to inspect and examine the components we build.
There are several different uses, but I want to discuss the use of Shallow Rendering. Shallow rendering allows us to inspect the results of a component’s
render function, and see check what HTML and React components that particular component returns.
So, just to be sure, let’s make sure that the
TodoList returns an element with class “todo-list”, that it has a child element that greets the user (we can guess this by it having a class “greeting”), and that it will render
Todos for all of the Todos that are given to it.
A test suite for that might look like this:
Woah, okay, that’s a lot of information. Let’s break it up piece by piece.
The dependencies that I’ve loaded up are as follows:
Let’s go through these piece by piece.
To construct expect statements, I’m using Chai and jsxChai. These libraries will allow us to build expectations directly against JSX components, like
expect(component).to.equal(<Todo />) for example.
As of React 0.14.0, the main functionality of React is split into two dependencies,
ReactDOM. The former consists of all of the fundamental logic that React relies upon, and the latter gives us the virtual DOM into which we can render components and verify that they render the way we want to in the tests.
shallowTestUtils are two other optional React libraries provided by Facebook itself. They are going to be the primary libraries which will allow us to artificially render our components and inspect their inner workings.
Finally, we’re testing the
TodoList, so we need that, as well as its inner component,
Todo, which we’ll use in a test later on.
beforeEach simply sets up a suitable test environment for each test. Using
TestUtils.createRenderer(), it generates an object which can superficially render a React component and return that object which is rendered (in this case,
todolist). Since we declared
renderer beforehand, we now have access to them in the scopes of the test.
Test 1: The Todolist
As noted above, the
todolist variable is the object which is to be rendered. We can treat it like other React components and inspect its props - here we’re just making sure that it receives a
className of “todo-list”.
Test 2: The Greeting
As this test shows, not only can we inspect the rendered component itself, but its children as well. Since the children are delivered down through React components via props, we can obtain the children there. This test simply grabs the first child of the rendered component and ensures that it has a class of “greeting”.
Test 3: The Todos
findAllWithType method comes in super clutch right here.
It traverses the semi-rendered
TodoList and returns an array of all sub-components that are of the type passed in the second argument. This way, we can make sure that there are exactly as many
Todos as we expect (3, since we passed 3 in to the
TodoList), and they look like exactly what we expect.
But Wait, Jake! React Doesn’t work like that, does it?
I know what you may be thinking right now: If the
renderer renders a
TodoList that contains
Todos, shouldn’t the
Todos be rendered as well? Isn’t this almost a recursive process of rendering down to the smallest, dumbest sub-component?
No, because we’re using
shallowTestUtils! This tool allows us to inspect only the rendered output of that component itself, leaving all React subcomponents as unrendered. In this way, we only need to check that the correct props are passed to subcomponents, and don’t need to worry about their inner details here (we should definitely make a
Todo test though!)
Like, totally cool, right?
In this way, React components are made to be very prone to unit testing - we can test a parent component to make sure it renders the subcomponents it needs to, while not having to look at the entire DOM structure that gets rendered when that component is loaded in the browser. It’s really helpful, especially given the complicated nature of front-end and user-simulating tests. So, with your new knowledge of React’s Shallow Rendering, go forth and test!