Snapshot Testing with Jest. It’s not a Joke!

Getting Started Using Jest To Test Your React App

Jest

There are tons of different testing libraries out there, but for today I’m going to focus specifically on Jest and React testing.

Jest is a JavaScript testing platform made by Facebook. It’s excellent for testing React, but it can also be used to test other JavaScript frameworks.

We’re going to explore how to use Jest by writing tests for a small React app that I wrote as the front end for another post. Here are the app and the code that we will be testing.

What To Test

I’ve always had a bit of imposter syndrome surrounding testing. On the one hand, I can easily imagine a scenario in which I don’t write a test for something really important, and even though everything is passing, I end up accidentally breaking my app. On the other hand, I can also see myself writing tons of tests that are so fine-grained they aren’t necessary and take so much time to write that I never actually finish the project. So the first thing I wanted to figure out was, how do I find that sweet spot in the middle?

After doing some brief research, I found an article which lays out some totally reasonable guidelines about what to test.

  1. Does it render?
  2. Is the output correct?
  3. Test all states (Anything conditional should be tested)
  4. Test all events
  5. Test the edge cases (e.g., Are you rendering an array? what if its empty?)
OMG Can we start writing tests already?!?!

Setting up

To get started, we first need to install Jest:

yarn add --dev jest

Since we are going to want to test components we are also going to need:

yarn add --dev react-test-renderer

To help test our component that renders image files, we need jest-transform-stub which helps Jest deal with non-JavaScript assets.

yarn add --dev jest-transform-stub

If you’re using Babel you need babel-jest and babel-core:

yarn add --dev babel-jest babel-core

Now that we have our dependencies squared away, we need to go into the package.json file and change a few things.

To start, at the top level we need to add a “jest” key like this:

This is where you will put all of your config options. In our case, we set verbose to true so that we get a display of each test when we run them. We are using moduleNameMapper in conjunction with jest-transform-stub, which we installed earlier, to mock our image files when testing any components that contain images.

Next, we need to change the value of "test" to "jest" in “scripts”. Mine looks like this:

For reference, my package.json file ended up looking like this:

Before I start writing any tests, I’m going to create a __test__ folder inside src, and then I’ll build a separate file for each component that includes all the tests for that component. The name of the folder is important for Jest to function correctly.

Writing the Tests

The structure of tests in Jest is pretty straightforward. There is a test() method that you call every time you want to test something. It takes two arguments; The first is a string that describes what we are testing — this is for humans and gets printed to the terminal when you run the test. It mainly functions as a label. The second argument is a callback that contains the logic for the actual test.

In the example above, we can get a pretty good idea of how our tests will be written. Inside the callback, we call expect and pass it the thing that we are testing. We chain another function, called a matcher, to the expect (in this case toBe()) which takes the desired outcome as it’s argument. There are a lot of different matchers to choose from, based on the thing you are trying to test.

There is another syntax we can use which works the same way. We can call describe() just like we were calling test()and pass it arguments with the same structure. Inside of the callback, we can nest it() which also takes the same syntax as test().

The choice between the two seems to be mostly stylistic. Describe allows you to nest and group your tests. However, if the indentation is getting out of control you can just use test().

Snapshot Testing

Snapshot testing is exactly what you think it is. The first time the test is run, Jest creates a ‘snapshot file’ that it will compare your code against in the future. On future runs of the test, Jest will compare the output with the previous snapshot. If they match, you pass!

This does mean that if you change the structure of your component, you will need to update that snapshot file, which you can do with the following command:

jest --updateSnapshot

To test our React app, we use the react-test-renderer package that we installed earlier. It allows us to render our component and set it equal to a variable that we can then pass to our tests.

At the top of our test file, we need to import React, the component to be tested and TestRenderer. Let’s start with the CardBack component.

Since we need to pass CardBack a roll object as a prop, we should also create a fake one.

Then we use the create() method from react-test-renderer to render the component for testing and set it equal to a variable. Our first test can check that the component renders correctly by using the .toMatchSnapshot() matcher to compare it to the snapshot.

cardBack.test.js

If we run our test from the command line using

yarn test

It passes! So our component is rendering as expected. Since this is a pretty basic component, that’s probably all of the testing it requires for the moment. Since, we already included all of that mumbo-jumbo for mocking images, we can test the CardFront in almost exactly the same way.

cardFront.test.js

Nav is even simpler since it doesn’t require any props.

nav.test.js

Let’s see how we are doing:

We’ve gotten our test suite set up and built simple tests for our three basic components. Next time we can tackle the container components and look at how to test components with state and asynchronous functions like fetch requests!