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