This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

React Testing: Intro to Shallow Rendering

1:55 React lesson by

In this lesson, we walk through how to use one of React's Test Utilities (from the react-addons-test-utils package) called "Shallow Rendering". This lets us render our React component one level deep - without a DOM - so that we can write tests for it. It works kind of like ReactDOM.render, where the shallow renderer is a temporary place to "hold" your rendered component so that you can assert things about its output. Tests written using the shallow renderer are great for stateless or "dumb" components that simply have their props passed to them from a parent container or "smart" component. These shallow renderer tests work especially well with stateless function components. They also work well for "unit" tests where you want to make sure your code works in isolation.

NOTE: The React team has recommended composing the majority of your apps using these stateless "dumb" components, so the majority of lessons in this course will focus on writing simple unit tests for these stateless components using Shallow Rendering. If you also want to write tests for the stateful components that are tied to different components and state and can't be tested in isolation, you may want to look at using a DOM (with something like Karma or jsdom) and React's other test utilities like renderIntoDocument and Simulate. However, I've found that it is helpful to try to compose most of your project with simple, isolated, stateless or "pure" components that can be unit tested with Shallow Rendering, and then wrap these components with a few stateful or "impure" components that you can either not worry about testing (what I do most of the time because it is difficult to test stateful components), or write separate integration and functional tests for them using different tools.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

In this lesson, we walk through how to use one of React's Test Utilities (from the react-addons-test-utils package) called "Shallow Rendering". This lets us render our React component one level deep - without a DOM - so that we can write tests for it. It works kind of like ReactDOM.render, where the shallow renderer is a temporary place to "hold" your rendered component so that you can assert things about its output. Tests written using the shallow renderer are great for stateless or "dumb" components that simply have their props passed to them from a parent container or "smart" component. These shallow renderer tests work especially well with stateless function components. They also work well for "unit" tests where you want to make sure your code works in isolation.

_NOTE: The React team has recommended composing the majority of your apps using these stateless "dumb" components, so the majority of lessons in this course will focus on writing simple unit tests for these stateless components using Shallow Rendering. If you also want to write tests for the stateful components that are tied to different components and state and can't be tested in isolation, you may want to look at using a DOM (with something like Karma or jsdom) and React's other test utilities like renderIntoDocument and Simulate. However, I've found that it is helpful to try to compose most of your project with simple, isolated, stateless or "pure" components that can be unit tested with Shallow Rendering, and then wrap these components with a few stateful or "impure" components that you can either not worry about testing (what I do most of the time because it is difficult to test stateful components), or write separate integration and functional tests for them using different tools.

Avatar
Dean

It would be great if we can get at least one more video, in this series, to go over using jsdom (or similiar) and testing a stateful component. It is inevitable that we will need to do this. Granted, I haven't watched the last few vids with Redux, so that might solve my current curiosity of not having a test for a stateful component.

In reply to egghead.io
Avatar
Trevor

Hi Dean,

I agree it would be good to add at least one lesson showing DOM + stateful tests. However, my opinion is that these sorts of tests belong with your functional tests. You can test some state and interactions with shallow rendering as shown in this article: http://simonsmith.io/unit-testing-react-components-without-a-dom/. However, these tests don't really give much value IMO, which is why I didn't include them in this series. In my production apps, I add tests for all "unit" logic for stateless components, then set up non-react specific functional tests for the entire app interactions. In my experience, setting up the environment and tests for interactive and stateful React components (with Mocha + Karma or Jest or whatever) is more work than it is worth. I prefer to have QA handle test automation with functional tests. I might add to this course later with some of these tests, but I feel that the added complexity and bang to buck ratio makes it a lower priority :)

Hope this helps.

In reply to Dean
Avatar
uleen

amazing vim customization) can you share your config?

Avatar
Trevor

Hi Uleen,

Thanks! Its actually mostly vanilla Vim; here my minimal .vimrc: https://github.com/trevordmiller/settings/blob/master/dotfiles/.vimrc

In reply to uleen
Avatar
squirm-life

I get an error:

1) CoolComponent should...:
TypeError: Can't add property context, object is not extensible
at [object Object].ReactCompositeComponentMixin.mountComponent (nodemodules/react/lib/ReactCompositeComponent.js:154:18)
at [object Object].wrapper [as mountComponent] (node_modules/react/lib/ReactPerf.js:70:21)
at [object Object].ReactShallowRenderer.
render (nodemodules/react/lib/ReactTestUtils.js:392:14)
at [object Object].ReactShallowRenderer.render (node
modules/react/lib/ReactTestUtils.js:376:8)
at Context. (src/jsx/lifelock/components/credit/charts/utils/CoolComponent.spec.js:17:14)

import React from 'react';
import TestUtils from 'react-addons-test-utils';
import expect from 'expect';
// import getHistoryDates from './getHistoryDates';

const CoolComponent = ({greeting}) => (

Greeting
{greeting}

);

describe('CoolComponent', () => {

it('should...', () => {
const renderer = TestUtils.createRenderer();
renderer.render();
const output = renderer.getRenderOutput();
console.log(output);
});
});

I'm going to import React from React, then I'll grab the test utils from the official React add-ons test utils library, and finally I'll import my expect-assertion library from the Expect package. Now let's create a simple component, I'll call it coolComponent, and we will give it a greeting prop, and then we will render out that greeting. So now that we have a component ready, let's create a simple test. I've added a basic describe block and it block, so now we can use the shallow-renderer.

The first thing we need to do is create a place to store the shallow-renderer, so I'm going to say renderer, and then use the test utils, and call the createRenderer method. So what's happened here is that our renderer variable has become a temporary place where we can store the output of our component. With the shallow-renderer these components are only rendered one level deep so you don't need a DOM, it just gives you the object structure that you can assert things about.

So now we can use this variable and call the render method on it, which works in the same way ReactDOM.render works, so we can pass in coolComponent and give it a greeting prop, and now we can take a look at what this contains by calling the renderer.getRenderOuput method, and let's log that out so we can take a look at it. So now if I run my tests, we can see the object output of our shallow-renderer.

We have a type, and key, ref, and props, and more properties on this object here that we can use to write assertions for our tests. As you can see, this object is only one level deep of our rendered output. That makes writing unit tests a lot simpler because we only have to worry about the component, not the environment the component was rendered in.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?