How to Mock useInsertionEffect in React
This article provides a straightforward guide on how to mock the
useInsertionEffect hook in React using testing frameworks
like Jest or Vitest. You will learn why mocking this hook is
necessary—especially when testing components that utilize CSS-in-JS
libraries—and explore practical, step-by-step code examples to implement
these mocks in your test suites.
Why Mock useInsertionEffect?
The useInsertionEffect hook is designed for CSS-in-JS
library authors to inject styles into the DOM before any layout effects
(useLayoutEffect) run. Because it runs synchronously before
DOM mutations, it can sometimes cause issues in testing environments
like JSDOM, which may not fully support style tag injection or layout
calculations. Mocking this hook allows you to bypass style injection
during unit tests or assert that the hook was called with the correct
styling functions.
Method 1: Mocking with jest.spyOn (Recommended)
The cleanest way to mock useInsertionEffect for
individual test files is to use jest.spyOn. This allows you
to mock the hook’s behavior and restore it after your tests run.
import React from 'react';
import { render } from '@testing-library/react';
import MyStyledComponent from './MyStyledComponent';
describe('MyStyledComponent', () => {
let useInsertionEffectSpy;
beforeEach(() => {
// Mock useInsertionEffect to execute the callback immediately
useInsertionEffectSpy = jest.spyOn(React, 'useInsertionEffect')
.mockImplementation((effect) => effect());
});
afterEach(() => {
// Restore the original implementation
useInsertionEffectSpy.mockRestore();
});
it('renders correctly with mocked style insertion', () => {
const { container } = render(<MyStyledComponent />);
expect(container).toBeInTheDocument();
expect(useInsertionEffectSpy).toHaveBeenCalled();
});
});Method 2: Global Module Mocking
If you need to mock useInsertionEffect across your
entire test suite, you can mock the react module globally.
This is useful if multiple third-party dependencies rely on the hook and
cause issues in your JSDOM environment.
Create or update your Jest setup file (e.g.,
setupTests.js) with the following code:
jest.mock('react', () => {
const originalReact = jest.requireActual('react');
return {
...originalReact,
// Mock useInsertionEffect to act like a standard useEffect/useLayoutEffect
useInsertionEffect: jest.fn((effect) => effect()),
};
});Method 3: Mocking in Vitest
If you are using Vitest instead of Jest, the syntax is highly
similar. You can use vi.spyOn to mock the hook
dynamically:
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import React from 'react';
import { render } from '@testing-library/react';
import MyStyledComponent from './MyStyledComponent';
describe('MyStyledComponent in Vitest', () => {
let useInsertionEffectSpy;
beforeEach(() => {
useInsertionEffectSpy = vi.spyOn(React, 'useInsertionEffect')
.mockImplementation((effect) => effect());
});
afterEach(() => {
useInsertionEffectSpy.mockRestore();
});
it('should render successfully', () => {
render(<MyStyledComponent />);
expect(useInsertionEffectSpy).toHaveBeenCalled();
});
});