How to Mock the Virtual DOM in React
Testing React components often requires simulating how they render and interact with the DOM. This article explains how to mock the Virtual DOM in React using popular testing libraries like Jest and React Testing Library, explores when and why you should mock it, and provides practical code examples to guide you through the process.
Understanding Virtual DOM Mocking
In React, you rarely mock the Virtual DOM engine itself. Instead, you
mock the environment in which the Virtual DOM operates (using
jsdom) or mock specific React components to prevent them
from rendering their virtual tree. This allows you to isolate the
component under test and speed up execution.
Step 1: Setting up JSDOM (The Mocked Browser Environment)
Most React testing frameworks, like Jest, use jsdom by default. JSDOM is a pure-JavaScript implementation of web standards that runs in Node.js. It acts as the mocked browser DOM where React’s Virtual DOM can safely mount and update.
If you are using Jest, ensure your configuration file
(jest.config.js) has the environment set to
jsdom:
{
"testEnvironment": "jsdom"
}Step 2: Mocking Component Render Trees
When unit testing a parent component, you may want to mock its child components to avoid rendering their entire Virtual DOM subtrees. This is called shallow rendering or component mocking.
Here is how you can mock a child component using Jest:
import { render, screen } from '@testing-library/react';
import ParentComponent from './ParentComponent';
// Mock the child component to prevent its Virtual DOM from rendering
jest.mock('./ChildComponent', () => {
return function DummyChild() {
return <div data-testid="mock-child">Mocked Child Content</div>;
};
});
test('renders parent component with mocked child', () => {
render(<ParentComponent />);
// Verify the parent renders, but uses the mocked version of the child
const childElement = screen.getByTestId('mock-child');
expect(childElement).toBeInTheDocument();
expect(childElement).toHaveTextContent('Mocked Child Content');
});Step 3: Mocking DOM APIs Not Supported by the Virtual DOM
Sometimes your React components interact with browser APIs that
jsdom does not fully support (such as
window.scrollTo, IntersectionObserver, or
ResizeObserver). To prevent your Virtual DOM tests from
crashing, you must mock these global objects.
You can add these mocks directly to your Jest setup file:
// Mocking window.scrollTo
Object.defineProperty(window, 'scrollTo', {
value: () => {},
writable: true,
});
// Mocking IntersectionObserver
global.IntersectionObserver = class IntersectionObserver {
constructor() {}
observe() {}
unobserve() {}
disconnect() {}
};Best Practices for Virtual DOM Testing
- Avoid manual DOM manipulation: Do not try to manually update the mocked DOM elements. Let React’s Virtual DOM handle the updates by triggering user events.
- Test behavior, not implementation: Use React Testing Library to interact with the rendered output as a user would (e.g., clicking buttons, typing in inputs) rather than testing the internal state of the Virtual DOM.
- Keep mocks minimal: Only mock child components or browser APIs that are third-party dependencies, network-dependent, or computationally expensive.