React Unit Test with Jest and Enzyme

Creating automated tests is crucial in any real-world project, although it can be a challenging task, especially in the frontend domain.

Fortunately, Jest, a testing tool developed by Facebook, simplifies unit testing in JavaScript. Additionally, Enzyme is a React-specific tool that offers a variety of useful methods to enhance the testing of React components.

By utilizing Jest and Enzyme, we can create more reliable and resilient React applications.

Set up a React application

To set up a React application, you first need to have Node.js and npm installed on your system. Once you have them installed, you can follow these steps:

Open your terminal and navigate to the directory where you want to create the project.

Run the following command to create a new React application:

$ npx create-react-app my-app

(Replace my-app with your preferred name for the project.)

Wait for the project to be created, and then navigate to the project directory by running:

$ cd my-app;npm start

This will open a browser window with the React application running.

Open the src/App.js, and write code that counts a clicks of a button:

import React, { Component } from 'react';

class App extends Component {
  constructor() {
    super();
    this.state = {
      count: 0,
    }
  }

  makeIncrease = amount => () =>
    this.setState(prevState => ({
      count: prevState.count + amount,
    }));

  increase = this.makeIncrease(1);

  render() {
    return (
      <div>
        <h1>Click it, and count it!</h1>
        <h3>Count: {this.state.count}</h3>
        <button className="increase" onClick={this.increase}>Click me to count</button>
      </div>
    )
  }
}

export default App;

The React application starts with an initial state of count set to zero, and a button that, upon being clicked, triggers the increment function which adds 1 to the count value and updates the state of the application.

Jest setting

The src/App.test.js file already contains a test case that verifies the App component’s ability to render without any errors.

import { render, screen } from '@testing-library/react';
import App from './App';

test('renders header', () => {
  render(<App />);
  const headerElement = screen.getByText(/Click it, and count it!/i);
  expect(headerElement).toBeInTheDocument();
});

Run the test and see the result.

// make sure the package.json has the test script.
// "test": "react-scripts test",

$ npm test

Add your Test

For React test, we need to render the pages(components), to render the pages, we will need to use and install additional packages – Enzyme

$ npm i --save-dev enzyme enzyme-adapter-react-16

Now, open stepupTests.js in root directory, and imports enzyme and enzyme-adapter-react-16.

.import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

Open the App.test.js, and add.

import React from 'react';
import { shallow } from 'enzyme';
import App from './App';

describe('Click it Count it starts', () => {
  it('starts with 0', () => {
    const wrapper = shallow(<App />);
    const text = wrapper.find('h3').text();
    expect(text).toEqual('Count: 0');
  });
});

We’re utilizing Enzyme’s shallow rendering feature to test our app’s starting state. Shallow rendering simulates the rendering of a component tree without requiring a DOM. It renders only one level deep of components, allowing us to examine the component’s contents and simulate user interactions.

The code snippet above stores the shallow render of our App component in the wrapper variable. Then, we retrieve the text that is enclosed in the p tag from the component’s output, and verify whether it is equivalent to the value passed to the toEqual matcher function.

Testing interaction

Add additional test case:

...
it('click it, increase it by 1', () => {
    const wrapper = shallow(<App />);
    const increaseBtn = wrapper.find('button.increase');
    increaseBtn.simulate('click');
    const text = wrapper.find('h3').text();
    expect(text).toEqual('Count: 1');
});
...

The simulate() function can simulate various DOM events on an element, and in this case, it is used on the button variable to simulate the click event. Additionally, we have set an expectation that the count state should be equal to the current value of now.

If you observe the terminal output, you will notice that the test passes as expected.

Now, we will take a different approach and add a test for a feature that does not exist yet, and then proceed to write the code to fulfill the test. This approach of writing tests before writing code is commonly known as Test Driven Development (TDD).

Add another test to the describe() function with the following format:

Testing with snapshot

Snapshot testing is a useful method to ensure that the rendered output of a component is consistent over time. Essentially, when you run a snapshot test, Jest generates a JSON file containing the rendered output of the React component being tested. Upon subsequent test runs, Jest will compare the output of the component with what was previously saved in the JSON file. If there are any differences detected, Jest will notify you, allowing you to update the snapshot to the latest version or fix the component so that it matches the snapshot again. This approach is helpful in preventing unintended changes to your components because Jest will always alert you when a difference is detected.

 react-test-renderer, which can be installed:

$ npm i --save-dev react-test-renderer

Next, import the react-test-renderer, create a test below all the previously created ones:

import renderer from 'react-test-renderer';
...
it('check the snapshot', () => {
    const tree = renderer.create(<App />).toJSON();
    expect(tree).toMatchSnapshot();
});
...

Upon the first execution of this test, Jest generates a snapshot for this component since none exists. The snapshots are stored inside the src/__snapshots__ directory and can be inspected to see the saved output of the component.

Run the test, then you will see output in  App.test.js.snap.

Check my repo – jest-unittest-app, you will have better idea.


Posted

in

by

I am a software engineer who enjoys building things. Please share your interest with me – chrisyoum[at]gmail.com