Accelerate your React testing with Enzyme
React’s virtual DOM offers some interesting opportunities for simplifying the process of testing, and Airbnb’s Enzyme framework makes testing your components an absolute pleasure. We recently tried out Enzyme on a React project at Brewhouse. We were blown away by how much simpler it was to write tests, and we’re never looking back.
It’s not the only option, of course. React itself offers the ReactTestUtils library - in fact, Enzyme depends on this for its integration with React. But Enzyme’s jQuery-style approach to node selection and manipulation makes it super familiar and really easy to work with.
Let’s investigate how we can put Enzyme to work. To demonstrate some of its features, I put together a small little app called Gif Grabbr. It uses the GIPHY API to find random GIFs based on your search. Take it for a spin first, then come back here to check out some code.
(Note: In the examples below I’m using Mocha with Chai and Karma as the test runner, but Enzyme can be used with pretty much any testing setup. Have a look at the Gif Grabbr source to see more details about my setup.)
Enzyme’s biggest strength is its shallow rendering capabilities. Not only does this encourage you to limit the scope of your tests to a single component, it also prevents errors deep in your node tree from affecting all your tests, and removes the requirement to mock a ton of objects.
App component in GIF Grabbr, which is the root component within which everything else is rendered:
To ensure the stability of my tests, as well as for performance reasons, I can use
.shallow() to render this component only one level deep:
This gives me a
ShallowWrapper object which I can do all sorts of fun stuff with. To illustrate how Enzyme is handling this render, let’s use
.debug() to take a look at the output:
.debug() returns a HTML-ish string representing the rendered output. Notice that the shallow render didn’t touch the
ImageDisplay components, but it did pass in any props that were available at the time. In our tests, this allows us to verify that a child component would have received the correct props without needing to actually render the thing.
Put the ‘$’ back in DOM traversal
Enzyme’s three flavours of rendering (shallow, full, and static) all return wrapper objects which give you jQuery-style power over your node tree. No longer must you wade through a jungle of nested arrays in order to test some deep-level node:
Using the wrapper I get from
.shallow(), I can just search for the image tag instead of needing to know exactly where it is in the node tree. This encourages a more declarative form of testing, minimizing your tests’ reliance on a specific tree structure.
Enzyme Selectors FTW
The selector is more than meets the eye. In addition to CSS-style selectors, an Enzyme Selector can find nodes by their component constructor, display name, even object properties:
Enzyme gives you a concise and elegant way of simulating user events, one of the trickier aspects of UI testing. Just pass the name of the event you want to simulate, along with any required data:
It’s also worth noting that the event argument can be anything you want. Unlike ReactTestUtils, you’re not limited to only events that React understands. Following convention, you could call
wrapper.simulate('donut') and Enzyme would simply look for an
onDonut event handler. Pretty neat.
Enzyme is an elegant and powerful way of testing your React applications. It can significantly increase the brevity of your tests thanks to its selector engine, and its approach to event simulation is quite promising. It also plays nicely with most test suites and assertion libraries out there, so you probably don’t need to change your workflow to start using it today.