🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
REFERENCEreact

react Documentation

LOADING ENGINE...

Component Testing with Enzyme

AI & DATA SCIENCE // enzyme

Enzyme was a popular React testing utility for shallow and full DOM rendering, allowing tests to inspect and interact with a component's internal implementation details — it has since fallen out of favor in modern React testing.

Syntax

import { shallow } from 'enzyme';
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.title').text()).toBe('Hello');

Deep Dive Course

Enzyme provided several rendering modes, most notably shallow(), which renders only one level deep, treating child components as opaque placeholders rather than fully rendering them, and mount(), which renders the full component tree into a real DOM. Enzyme's API encouraged querying and asserting against a component's internal structure and implementation, like directly finding a specific child component by name or inspecting internal state, which meant tests could pass or fail based on internal refactoring details that a real user would never actually notice or care about — this implementation-detail coupling is the main reason the React community has largely moved toward React Testing Library instead, which deliberately queries the rendered output the way a real user would.

1Understanding Component Testing with Enzyme

Enzyme provided several rendering modes, most notably shallow(), which renders only one level deep, treating child components as opaque placeholders rather than fully rendering them, and mount(), which renders the full component tree into a real DOM. Enzyme's API encouraged querying and asserting against a component's internal structure and implementation, like directly finding a specific child component by name or inspecting internal state, which meant tests could pass or fail based on internal refactoring details that a real user would never actually notice or care about — this implementation-detail coupling is the main reason the React community has largely moved toward React Testing Library instead, which deliberately queries the rendered output the way a real user would.

💡

If you're maintaining an older codebase using Enzyme, be aware that shallow rendering doesn't render child components at all, so any assertion depending on a child component's actual rendered output requires mount() instead, not shallow().

editor.html
import { shallow } from 'enzyme';
import Greeting from './Greeting';

test('renders a greeting', () => {
  const wrapper = shallow(<Greeting name="Ana" />);
  expect(wrapper.text()).toContain('Ana');
});
localhost:3000

2Practical Example

Here is a real-world application of Component Testing with Enzyme showing how it is used in production React code.

editor.html
import { shallow } from 'enzyme';

test('finds internal state directly, an implementation-detail-coupled test', () => {
  const wrapper = shallow(<Counter />);
  expect(wrapper.state('count')).toBe(0);
});
localhost:3000

3Best Practices

Follow these guidelines when working with Component Testing with Enzyme:

1. Recognize Enzyme as a largely legacy tool at this point, favoring React Testing Library for any new test code in a modern React codebase

2. Understand that shallow() renders only one level, treating children as placeholders, while mount() renders the full DOM tree, when maintaining existing Enzyme-based tests

3. Avoid writing new tests that assert on internal component state or implementation details, whether in Enzyme or any other tool, favoring user-visible behavior instead

⚠️

Tip: If you're maintaining an older codebase using Enzyme, be aware that shallow rendering doesn't render child components at all, so any assertion depending on a child component's actual rendered output requires mount() instead, not shallow().

editor.html
import { shallow } from 'enzyme';
import Greeting from './Greeting';

test('renders a greeting', () => {
  const wrapper = shallow(<Greeting name="Ana" />);
  expect(wrapper.text()).toContain('Ana');
});
localhost:3000

Examples

Example 01Basic Usage
import { shallow } from 'enzyme';
import Greeting from './Greeting';

test('renders a greeting', () => {
  const wrapper = shallow(<Greeting name="Ana" />);
  expect(wrapper.text()).toContain('Ana');
});
Example 02Advanced Example
import { shallow } from 'enzyme';

test('finds internal state directly, an implementation-detail-coupled test', () => {
  const wrapper = shallow(<Counter />);
  expect(wrapper.state('count')).toBe(0);
});

Best Practices

  • Recognize Enzyme as a largely legacy tool at this point, favoring React Testing Library for any new test code in a modern React codebase
  • Understand that shallow() renders only one level, treating children as placeholders, while mount() renders the full DOM tree, when maintaining existing Enzyme-based tests
  • Avoid writing new tests that assert on internal component state or implementation details, whether in Enzyme or any other tool, favoring user-visible behavior instead

Interview Question

Why did the React community largely move away from Enzyme's approach of asserting against a component's internal state and implementation details, toward React Testing Library's user-facing querying instead?

Hint: Think about what should actually cause a test to fail — a change to how a component's UI/behavior appears to a real user, or a change to how that component happens to be implemented internally.

A test that reaches directly into a component's internal state or implementation, like Enzyme's wrapper.state() or directly finding an internal child component by name, ties the test's pass/fail outcome to details that are genuinely irrelevant to whether the component actually works correctly from a real user's perspective — refactoring a component's internal state variable name, or restructuring which sub-components it happens to use internally, can break such a test even though the component's actual rendered output and behavior, what a real user would ever see or interact with, hasn't changed at all. This produces brittle tests that fail for the wrong reasons, discouraging legitimate refactoring since developers become wary of breaking tests that don't actually reflect real regressions. React Testing Library's philosophy of querying and interacting with a component the way a real user would, by visible text, labels, and roles, rather than internal implementation, means a test only fails when the component's actual user-facing behavior genuinely changes, which is a much more meaningful and stable signal of an actual regression.

Exercises

MediumPractice using Component Testing with Enzyme in a real scenario.
View Solution
import { shallow } from 'enzyme';
import Greeting from './Greeting';

test('renders a greeting', () => {
  const wrapper = shallow(<Greeting name="Ana" />);
  expect(wrapper.text()).toContain('Ana');
});

Frequently Asked Questions

Why did the React community largely move away from Enzyme's approach of asserting against a component's internal state and implementation details, toward React Testing Library's user-facing querying instead?

A test that reaches directly into a component's internal state or implementation, like Enzyme's wrapper.state() or directly finding an internal child component by name, ties the test's pass/fail outcome to details that are genuinely irrelevant to whether the component actually works correctly from a real user's perspective — refactoring a component's internal state variable name, or restructuring which sub-components it happens to use internally, can break such a test even though the component's actual rendered output and behavior, what a real user would ever see or interact with, hasn't changed at all. This produces brittle tests that fail for the wrong reasons, discouraging legitimate refactoring since developers become wary of breaking tests that don't actually reflect real regressions. React Testing Library's philosophy of querying and interacting with a component the way a real user would, by visible text, labels, and roles, rather than internal implementation, means a test only fails when the component's actual user-facing behavior genuinely changes, which is a much more meaningful and stable signal of an actual regression.

Related Functions

react-testing-librarycomponent-testingjest