How to Mock Higher-Order Components in React
Mocking Higher-Order Components (HOCs) in React is an essential skill for writing clean, isolated unit tests. This article explains why you should mock HOCs and demonstrates the most effective strategies to do so using Jest, including using identity mocks, injecting mock props, and exporting unwrapped components for direct testing.
Why Mock Higher-Order Components?
HOCs are functions that take a component and return a new component, usually injecting extra behavior, state, or props (such as routing, Redux state, or authentication). When unit testing a wrapped component, you want to test its core rendering and business logic in isolation. Mocking the HOC allows you to bypass external dependencies, API calls, or complex authentication checks, ensuring your tests remain fast, predictable, and focused.
Method 1: Exporting the Unwrapped Component
The cleanest and most straightforward way to bypass an HOC in tests is to export the unwrapped component as a named export, while exporting the wrapped version as the default export.
// MyComponent.js
import React from 'react';
import { withAuth } from './withAuth';
// Export the unwrapped component for testing
export const MyComponent = ({ user }) => {
return <div>Welcome, {user.name}</div>;
};
// Export the wrapped component for production use
export default withAuth(MyComponent);In your test file, you import the unwrapped component directly by using curly braces:
// MyComponent.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import { MyComponent } from './MyComponent'; // Named import bypasses the HOC
test('renders welcome message with user name', () => {
render(<MyComponent user={{ name: 'Alice' }} />);
expect(screen.getByText('Welcome, Alice')).toBeInTheDocument();
});Method 2: Mocking the HOC Module as an Identity Function
If you cannot or do not want to alter your component exports, you can
mock the HOC at the module level using jest.mock(). You can
write an “identity mock” that takes the component and returns it without
any modifications.
// MyComponent.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent'; // Default wrapped import
// Mock the HOC file to return an identity function
jest.mock('./withAuth', () => ({
withAuth: (Component) => (props) => <Component {...props} />,
}));
test('renders component by mocking the HOC wrapper', () => {
render(<MyComponent user={{ name: 'Bob' }} />);
expect(screen.getByText('Welcome, Bob')).toBeInTheDocument();
});Method 3: Mocking HOCs that Inject Props
If the wrapped component relies on props injected by the HOC, your mock must provide those expected props so the component does not crash during rendering.
// MyComponent.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
// Mock the HOC and inject mock props automatically
jest.mock('./withAuth', () => ({
withAuth: (Component) => (props) => (
<Component {...props} user={{ name: 'Mocked User' }} />
),
}));
test('renders component with injected HOC props', () => {
render(<MyComponent />);
expect(screen.getByText('Welcome, Mocked User')).toBeInTheDocument();
});