Unit testing React components with shallow rendering
So you’ve created an awesome react component that displays a group of buttons. Finally, that Button component your colleague Bob wrote is actually useful for something!
But you’ll need to write some unit tests in case Bob breaks your component in one of his notorious refactoring binges.
One way of doing this is to render the component and test the output, but that means you’ll be testing Bob’s Button component as well as your own code. Every time someone changes Button, your tests will fail even though your component it still working perfectly.
Luckily the React team have introduced shallow rendering to solve this problem. It allows you to render a component while leaving sub-components as unrendered JSX. This means you can write unit tests like these:
Notice how the Button component remains opaque so we don’t have to worry about how its JSX will be rendered. We can just check that it is being rendered in the right place, the right number of times, with the right props.
Better yet, because our ButtonGroup component is now pure we can use parameterised tests; we say what parameters we’re passing to the component and specify the output we expect to be rendered e.g. when we pass true for the “disabled” prop we expect the btn-group div to be rendered with the disabled attribute. This makes writing unit tests quick and easy.
So far all we’ve done is create an array describing our tests. We still need to write the testComponent function which shallowly renders our component and compares the the output to our “expected” parameter.
So what’s going on here?
We’re importing the ReactTestUtils library which will give us the ability to shallowly render our component so we can compare the rendered output to our expected value.
We’re also importing Chai and jsxChai which we’ll be using to test equality between the expected and actual output. By default Chai doesn’t understand JSX so we tell it to use jsxChai.
The test component takes a single argument which is an array of objects each having a “component” and an “expected” property. We’ll iterate over this array to run each test.
ReactTestUtils has a createRenderer method which allows us to create a renderer with shallow rendering capability. When we pass our component to the renderer’s render method it will only render the top level of JSX and leave all sub-components unrendered. Then we can grab the output and assign it to a variable by calling getRenderedOutput.
Finally we use chai to compare the rendered output to what we were expecting.
Now we have the testComponent function we can write parameterised tests for all of our react components. Bob could even use it to test Button.