Unit Testing in React with Jest and Enzyme Frameworks

    Jul 17, 202410 min read1225 viewsUpdated:Apr 3, 2025
    Unit Testing in React with Jest and Enzyme Frameworks

    Unit testing is a key role in maintaining code quality and reliability, especially in React apps where components often changes. This blog covers how to test React components using two of the most popular test utilities used in the React community: Jest and Enzyme. We will discuss the significance of unit testing, tools used, and practices such as Test-Driven Development (TDD), snapshot testing, and others.

    Table of Contents

    1. Introduction to Testing

    2. What is Unit Testing and Its Significance?

    3. Why is Unit Testing Important?

    4. Introduction to Jest and Enzyme?

    5. What is React Testing Library

    6. Setting Up Jest and Enzyme for React Testing

    7. Writing Unit Tests for React Components with Jest and Enzyme

    8. Why Use TDD to Create a React.js Component?

    9. How Do We Unit Test a React.js Component?

    10. Testing React Components with Snapshots

    11. Common Testing Strategies for React Components

    12. Conclusion

    Introduction to Testing

    Unit testing is one of the most fundamental step of the software development process, it confirms that every single little portion of your code functions well. In React.js, unit tests assist programmers in checking whether single components function well or not under various situations. Jest and Enzyme are strong utilities that make testing easy and enable us to test React components in isolation thoroughly.

    Testing becomes especially necessary for React components because:

    • Components tend to get reused, and assure each of them function correctly in a variety of use cases which is essential in keeping a healthy codebase.

    • React apps are event-driven, and testing the way components handle events and interactions is essential in order to make sure there is a smooth user experience.

    What is Unit Testing and Its Significance?

    Unit testing involves testing individual parts or functions in isolation. In the case of React, a unit test typically involves testing a single React component and its functionality, such as rendering, handling state changes, and responding to user input.

    Why is Unit Testing Important?

    Reliability: Unit tests makes sure that every component is functioning correctly, by testing multiple components in isolation, you can see problems in parts of your application.

    Early Bug Detection: Writing unit tests avoids bugs before they reach your users by catching them early in the development process. You can automatically test as you code to avoid code changes causing bugs With Jest and Enzyme.

    Refactoring Confidence: Unit tests assure you that the component still works as expected whenever you refactor const component or change your application. If any tests break, you can immediately identify where the issue occurred.

    Documentation: Unit tests can be used as documentation, as describing a component's behavior. Other developers can look at your tests to see how the component is supposed to work without being required to read the entire source code.

    In addition to these benefits, unit testing helps improve the maintainability and quality of the application component codebase. In large-scale projects, unit testing is a safeguard, ensuring that the fundamental functionality of the app component is stable despite the addition of new features or changes to existing ones.

    Introduction to Jest and Enzyme

    Jest: Test Runner and Assertion Library

    Jest is an open-source testing framework developed by Facebook, and it is widely used to test React and JavaScript applications. It is more advantageous because it has both a test runner and an assertion library packaged into one package, and users can easily write test cases and build test environments.

    Key Features of Jest:

    Snapshot Testing: Jest enables you to save the rendered result of your components as a "snapshot." In subsequent test runs, the component's current output is compared against the saved snapshot, and you can detect any unanticipated differences.

    Automatic Mocking: Jest automatically supports mocking modules and functions, which allows you to isolate components by managing dependencies in your tests.

    Code Coverage: Jest can provide reports on which lines of code are being tested and ensure your whole application is being tested.

    Parallel Test Running: Tests are executed in parallel by Jest, making the testing process quicker, particularly for complex codebases.

    Effortless Installation: Jest seamlessly integrates with React applications and can be installed by running npm install --save-dev jest.

    Enzyme: A JavaScript Testing Utility for React

    Enzyme is a JavaScript testing library developed by Airbnb to test React components. It has numerous ways to render and test files that are compatible with these components and works seamlessly with Jest.

    Major Characteristics of Enzyme

    Shallow Rendering: Shallow rendering is best suited to test a component in isolation.This will render a component but not the child components. Shallow rendering is a testing techelpshnique used to render only the component being tested, without rendering its child components. This you test a component in isolation, making it easier to focus on its own behavior and output, without worrying about how its children behave.

    Full DOM Rendering: It gives the ability to emulate user behavior, like form submissions and clicks. This is particularly useful when it's necessary to analyze how components are communicating with each other.

    Static Rendering: This method allows the creation of the component's static HTML, which can be used to compare or to test the rendered markup.

    Component Interaction: Enzyme offers additional functionality, such as simulate() to emulate events such as clicks, input field value changes, and form submissions.

    Example of Enzyme with Jest:

    import { shallow } from 'enzyme';
    import MyComponent from './MyComponent';
    
    test('renders correctly', () => {
      const wrapper = shallow(<MyComponent />);
      expect(wrapper).toMatchSnapshot();
    });
    

    What is React Testing Library

    Another test utility that has become popular with React developers is the React Testing Library (RTL). Unlike Enzyme, a test suite that focuses on testing implementation details, RTL asks React app developers to test components from the user's point of view in terms of how users interact with React components and what the app does with them.

    Key Features of React Testing Library:

    User-Centric Testing: RTL promotes testing of components in the manner in which the users interact with them, by button clicking, form submission, and confirmation of user interface changes.

    Basic Queries: It offers basic DOM queries such as getByText(), getByRole(), and getByLabelText(), which make it easy to locate and interact with elements in the rendered output.

    No Shallow Rendering: RTL doesn't use shallow rendering. Instead, it encorages rendering the entire component with its children, a more accurate method of testing.

    Setting Up Jest and Enzyme for React Testing

    Before we cover writing tests, let’s set up Jest and Enzyme in your React project.

    Step 1: Install Jest and Enzyme

    Start by installing Jest, Enzyme, and related dependencies:

    npm install --save-dev jest enzyme enzyme-adapter-react-16 @testing-library/react

    enzyme-adapter-react-16 is required to make Enzyme compatible with React 16. If you are using React 17 or React 18, make sure to use the appropriate Enzyme adapter version.

    Step 2: Configure Enzyme

    Next, you need to configure Enzyme with the correct React adapter. Create a setup file for Jest (e.g., src/setupTests.js), and add the following code:

    import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; // Configure Enzyme to use the React 16 adapter configure({ adapter: new Adapter() });

    Step 3: Running Tests

    To run your tests, simply run the following command:

    npm test

    This will launch Jest’s test runner and execute the tests in your project.

    Example of RTL Test:

    import { render } from '@testing-library/react';
    import MyComponent from './MyComponent';
    
    test('renders component text', () => {
      const { getByText } = render(<MyComponent />);
      const textElement = getByText(/Hello World/i);
      expect(textElement).toBeInTheDocument();
    });
    

    How Do We Unit Test a React.js Component?

    Now that we have everything set up, let's look at how to write unit tests for React components using Jest and Enzyme.

    Example 1: Shallow Rendering and Testing a Simple Component

    Consider a simple Button component that increments a count every time it's clicked:

    import React, { useState } from 'react'; const Button = () => { const [count, setCount] = useState(0); const handleClick = () => { setCount(count + 1); }; return ( <button onClick={handleClick}> Clicked {count} times </button> ); }; export default Button;

    Test: Verifying Button Click Behavior

    Let's write a unit test to verify that the button increments the count when clicked.

    import { shallow } from 'enzyme'; import Button from './Button'; test('increments count on button click', () => { const wrapper = shallow(<Button />); // Initial count should be 0 expect(wrapper.text()).toBe('Clicked 0 times'); // Simulate a button click wrapper.find('button').simulate('click'); // The count should be incremented to 1 expect(wrapper.text()).toBe('Clicked 1 times'); });

    shallow(): This function renders the component without rendering its children, which makes it ideal for unit testing.

    simulate(): Simulates user interactions like clicks, input changes, etc.

    expect(): Used to assert that the component behaves as expected.

    Example 2: Full DOM Rendering for Component with Child Components

    Sometimes, you need to test how a component interacts with its children. In such test cases only, you can use full DOM rendering.

    Parent Component:

    import React, { useState } from 'react'; import Child from './Child'; const Parent = () => { const [message, setMessage] = useState('Hello'); const handleChangeMessage = () => { setMessage('Goodbye'); }; return ( <div> <button onClick={handleChangeMessage}>Change Message</button> <Child message={message} /> </div> ); }; export default Parent;

    Child Component:

    import React from 'react'; const Child = ({ message }) => { return <p>{message}</p>; }; export default Child;

    Test: Verifying Interaction Between Parent and Child Components

    import { mount } from 'enzyme'; import Parent from './Parent'; import Child from './Child'; test('Parent and Child components interact correctly', () => { const wrapper = mount(<Parent />); // Verify initial message in the child component expect(wrapper.find(Child).prop('message')).toBe('Hello'); // Simulate button click to change the message wrapper.find('button').simulate('click'); // Verify the updated message in the child component expect(wrapper.find(Child).prop('message')).toBe('Goodbye'); });

    In this example, mount() is used to fully render both the parent and child components to test the interaction between them.

    Why Use TDD to Build a React.js Component?

    Test-Driven Development (TDD) is a method where tests are written before the code. It leads to better design decisions, increased testing utilities integrated tools, higher quality code, and fewer bugs.

    Advantages of Applying TDD with React:

    Better Component Design: Test writing first leads to better component function and design.

    Fewer Bugs: TDD facilitates early detection of bugs, which plays an essential part in maintaining bug-free, top-notch code.

    Simplified Refactoring: Since tests validate functionality, you can refactor knowing that the tests will catch any unintended changes.

    TDD Process for React Components:

    1. Create a test for the anticipated behavior of a failing component.

    2. Code the bare minimum required to make the test pass.

    3. Refactor the code to make it more efficient or readable without losing any of the tests.

    4. Repeat the loop for each new feature or update.

    Testing React Components with Snapshots

    Snapshot testing is a powerful feature in Jest, which allows developers to capture the rendered output of components at a assigned time and compare it against future snapshots to identify the unintended changes.

    Steps to Implement Snapshot Testing:

    Capture the Snapshot: The first time you run the test, Jest captures the component’s rendered output and saves it in a snapshot file.

    Compare Snapshots: For subsequent test runs, Jest compares the current output with the saved snapshot. If there’s a difference, Jest will report it as a failure.

    Update Snapshots: If the llllchanges are intentional, you can update the snapshot by running npm test -- -u.

    Snapshot Testing Example:

    import { render } from '@testing-library/react';
    import MyComponent from './MyComponent';
    
    test('matches snapshot', () => {
      const { asFragment } = render(<MyComponent />);
      expect(asFragment()).toMatchSnapshot();
    });

    Common Testing Strategies for React Components

    Testing is an essential part of the development process to confirm the correctness and reliability of your React application. Below are some common testing techniques you can employ when composing tests for React components:

    Improve Your React App’s Reliability and Maintainability At Angular Minds, we deliver high-quality, bug-free development with expert unit testing using Jest & Enzyme. Partner with the best React development company today.

    1. Testing Component Rendering

    This technique involves testing the component rendering as it relates to props and state. You can validate that the component is displaying the correct information and also processing the updates to the state appropriately by checking the rendered output. This assures the UI presents the correct result for a number of different inputs.

    2. Event Simulation

    It is essential to test how a component reacts to user interaction, like clicks, form submission, or key presses. It ensures that the component functions as expected when users interacts with it. Whether the button is clicked, a form submitted, or the user interacting with a dropdown, event simulation tests enable you to ensure your component is responding properly to such actions.

    3. Mocking Functions

    In most instances, components communicate with outside systems such as APIs, or else depend on local helper functions. Mocking functions ensures that you isolate a component from what it depends on and enable the simulation of interactions without executing actual function calls. With libraries such as Jest's mock() or Enzyme's spyOn(), you're able to dictate how functions respond during the test, allowing you to have more controlled testing.

    4. State and Props Testing

    Testing state and props' impact on a component's output and behavior is crucial to the assurance that components render and behave as intended when their data varies. State testing guarantees that the component behaves appropriately when its internal data varies, while props testing guarantees that the component reacts appropriately to variations in the data passed to it by parent components. By checking both, you can guarantee that your components handle and display dynamic data correctly.

    5. Integration Testing

    Integration testing checks how various parts collaborate with one another when assembled together. It confirms that when parts are implemented in conjunction with each other, they function smoothly and that data moves successfully between them. Integration tests identify problems that are not evident while testing each component in isolation. They mimic the way parts work together in achieving complex operations and data sharing.

    6. Snapshot Testing

    Snapshot testing enables you to save the output of a component and then test whether its saved snapshot matches a new saved snapshot. It is helpful in identifying unintended changes to the rendered view of a component. Snapshot tests are able to rapidly identify whether there have been changes to the structure, styling, or content of a component, making it simpler to find regressions and achieve consistency in the UI.

    7. Error Handling and Boundary Testing

    Testing how a component behaves in case of errors is a significant approach, particularly for components that can potentially interact with flaky external services or data. Error boundaries are one of the standard methods to catch errors in React, and testing makes sure that they render fallback UI or give a graceful recovery when there's an error. This makes sure that your app doesn't crash at unexpected times and enhances user experience by offering an error message and a fallback mechanism.

    8. Asynchronous Testing

    Most React components have to deal with asynchronous operations like data fetching from an API or a backend service. Testing async operation-dependent components makes sure they work correctly with promises, the loading state, and errors. Testing of this sort ensures the component renders correctly when the async operation is over and deals with any failures that may occur smoothly.

    9. Accessibility Testing

    Accessibility is a priority issue for web applications today. Testing your React components for accessibility is a way to ensure they are accessible to people with disabilities. Techniques involve testing for correct usage of ARIA roles, keyboard navigation, and that screen readers can correctly understand the structure of the component. This can be achieved by using libraries such as axe-core or React Testing Library to detect accessibility issues during the early stages of development.

    10. Performance Testing

    Performance testing is the process of measuring how well components perform under different conditions, like with big data sets or heavy user interaction. By running tests that mimic high traffic or big data loads, you can determine where bottlenecks might occur and optimize the performance of your React components. This is particularly relevant for components that must deal with large amounts of data or run in real-time applications.

    Conclusion

    Unit testing is a critical process to achieve bug-free, high-quality React applications. Developers can thoroughly test their components using tools such as Jest, Enzyme, and the React Testing Library to simulate how the components are utilized and interact in real-world scenarios.

    Adding unit test cases to Test-Driven Development (TDD) provides improved code quality and fewer bugs which results in more reliable and maintainable React applications.

    Whether you're testing React components with Jest snapshots, simulating user interaction with Enzyme, or embracing the user-centric approach with React Testing Library, learning how to unit test React components is essential to create robust and maintainable web applications.

    24

    Related articles

    This website uses cookies to analyze website traffic and optimize your website experience. By continuing, you agree to our use of cookies as described in our Privacy Policy.