Skip to content

Instantly share code, notes, and snippets.

@Cool-Runningz
Last active March 30, 2019 04:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cool-Runningz/9be6f716c7e982e065f966ec6257e532 to your computer and use it in GitHub Desktop.
Save Cool-Runningz/9be6f716c7e982e065f966ec6257e532 to your computer and use it in GitHub Desktop.
Article on installation, configuration and getting up and running with unit testing with Jest and Enzyme.

Unit Testing with Jest & Enzyme

This article was created to help you get up and running with Jest and Enzyme. It will cover installing and configuring Jest and Enzyme (not using Create React App). Basic unit test examples can be found in the source code.

Disclaimer

All the information provided has been compiled and adapted from the references cited at the end and throughtout the document. The guidelines are illustrated by either my own examples or samples found when researching this topic. A big thanks to all the authors who wrote the sources of information.

Table of Contents

  1. Jest Overview
  2. Enzyme Overview
  3. Jest Installation
  4. Enzyme Installation
  5. Folder and File Structure
  6. Getting Started
  7. Jargon
  8. Writing Tests
  9. Testing Components
  10. Optional Installations
  11. Additional Resources

Jest Overview

Jest is a JavaScript testing library built by Facebook. Although Jest can be used to test any JavaScript library, it is extremely helpful when it comes to testing React code. It also allows you to create mock functions with almost zero configuration and provides a really nice set of matchers that makes assertions easier to read. There’s also a feature called “snapshot testing” which helps you check and verify the component rendering result.

Enzyme Overview

Enzyme is a React specific testing library (written by Airbnb) that allows you to manipulate and render components, access props and state, and more. It makes it easier to assert, manipulate, and traverse your React Components’ output.

Jest Installation

Jest is already configured when you use create-react-app but if you want to re-install it via npm use:

npm install --save-dev jest

Add the following section to your package.json file:

{
  "scripts": {
    "test": "jest",  
    "test:watch": "jest --watch",
    "test:coverage":  "jest --coverage"
  }
}

Enzyme Installation

  • To get started with enzyme, you can simply install it via npm. You will need to install enzyme along with an Adapter corresponding to the version of React (or another UI Component library) you are using. If you are using React 16, you can run:
npm install --save-dev enzyme enzyme-adapter-react-16 enzyme-to-json
  • Each adapter may have additional peer dependencies which you will need to install as well. Another dependency you will need to work with enzyme is react-test-renderer which you can install via npm:
npm install --save-dev react-test-renderer@16.5.2
  • There is a small amount of boilerplate code needed to integrate Enzyme with Jest and React. This will configure Enzyme to work with the adaptor that you want to use and will provide a global setup before running tests.

src/setupTests.js

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });
  • You use the enzyme-to-json package as the snapshot serializer in your Jest config. This automatically converts the shallow render into a much more human-readable format for the snapshot file and removes extra stuff from the Enzyme shallow wrapper that you don’t care about. To set this up you need to add to update package.json to reference the setupTests.js file:
"jest": {
  "snapshotSerializers": ["enzyme-to-json/serializer"],
  "setupTestFrameworkScriptFile": "<rootDir>/src/setupTests.js",
}

Folder and File Structure

Jest will look for test files with any of the following popular naming conventions:

  • Files with .js suffix in __tests__ folders.
  • Files with .test.js suffix.
  • Files with .spec.js suffix.

The .test.js and .spec.js files (or the __tests__ folders) can be located at any depth under the /src top level folder.

It is recommended to put the test files (or __tests__ folders) next to the code you are testing so that relative imports appear shorter. For example, if App.test.js and App.js are in the same folder, the test just needs to import App from './App' instead of a long relative path. Colocation also helps find tests more quickly in larger projects.

  • The first thing to do is to create a JS file that will contain the test function(s) that you will want to execute in the test file. (ex. math.js)
  • Each of these function files will contain a corresponding test file (ex. math.test.js) This test file will be where you will be running your tests that were defined in the other file.

Getting Started

  • Walkthrough of running a simple Jest test: https://jestjs.io/docs/en/getting-started
  • How to run a test:
    1. npm run test (Single run)
      • Runs all tests in the folder
    2. npm run test:watch (watchmode)
      • Watches files for changes and automatically re-runs tests for changed files

Jargon

  • The building block of any unit test is an assertion. An assertion is simply a way of expressing expectations on how something should behave.
  • There are multiple matchers in Jest, each aiding with a specific aspect of verification and some test if objects are equal etc. Jest matchers documentation
  • Jest makes available, as global variables, the describe, test, expect and a few other functions so you don’t need to import them. You can check out the full list here
  • Snapshot Testing allows you to compare a screenshot with changes that may have been made. If the screenshots don’t match, there are two possibilities: either the change is unexpected, or the screenshot can be updated to the new version of the UI component.
    • Can test component re-rendering to ensure that things look the way they should.
    • It’s basically a rendered output of your component stored in a text file.
    • It’s a useful testing tool if you want to ensure that the UI hasn’t changed.
    • Ideally there should only be one snapshot per component
    • You should push the snapshot into the repo and store it along with the test. If the component has been changed, you just need to update the snapshot with --updateSnapshot flag or use the short form -u flag
  • Shallow rendering renders only component itself without its children. If you change something in a child component it won’t change shallow output of your component. Or a bug, introduced to a child component, won’t break your component’s test. It also doesn’t require DOM.
  • snapshotSerializers allows you to pass Enzyme wrappers directly to Jest’s snapshot matcher, without converting them manually by calling enzyme-to-json’s toJson function.
  • Jest can collect code coverage information from entire projects, including untested files.

Writing Tests

  • In test files you will typically use the expect() function and toBe() or whatever in order to make sure the desired result is happening. Basically, you will always be making an assertion about what you are testing. You can find a list of all the available assertions in the Jest documentation.
  • When testing React components (Presentational), your tests should only be focused on what is being rendered and the client-side behavior.
  • It is recommended to test your interactions with the Redux store through tests covering your actions and reducers. However, you can test interactions with your store within your smart components.
  • When it comes to making actual assertions, you wrap the thing you want to test within an expect() call, before then calling an assertion on it.
    • The expect() function is used every time you want to test a value. You will rarely call expect() by itself. Instead, you will use expect along with a matcher function to assert something about a value.
  • You should use toBe() on primitive values, such as strings and numbers, but toEqual() on objects and arrays. toEqual() is built to deal with arrays and objects and will recursively check each field or item within the object given to ensure that it matches.
  • References

Testing Components

  1. Testing Basic Component Rendering
  2. Testing props (divide into two tests)
    • Check the render of default prop values (make sure default values are being set)
    • Check the custom value of the prop. (Does the custom prop you passed in override the default prop (if there is one) value OR does the custom prop take your value and apply it)
  3. Testing data types (See 'Optional Installations' section)
  4. Testing Conditions
    • Very often you can have conditions for the output of a particular class, rendering a certain section of the code, transferring the required props, and so on. Do not forget about this, because with default values, only one branch will pass the test, while the second one will remain untested.
    • In complex components with calculations and lots of conditions, you can miss some scenarios. To make sure all parts of the code are covered by tests, use a test coverage tool and visually check which scenarios are covered and which are not.
  5. Testing State
    • To check state, in most cases, it is necessary to write two tests:
      1. The first one checks the current state.
      2. The second one checks the state after calling an event. Render component, then call function directly in the test, then check how state has changed. To call the function of the component, you need to get an instance of the component and only then call its methods.

Optional Installations

If you want to address type checking and test data types then you can install a third-party library ‘jest-extended’ which would give you additional jest matchers that you can work with.

Additional Resources

In addition to the links cited throughout and as mentioned in the disclaimer, this article is a compilation of what I've learned from multiple resources. Below is a list of those resources. Again, a big thanks to all the authors who wrote the sources of information. I hope my article and these sources can help you out as well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment