How to Mock useState Hook in React
This article provides a straightforward guide on how to mock the
useState hook in React using Jest. You will learn the
step-by-step process of spying on the hook, overriding its default
behavior with custom mock functions, and verifying that state setters
are called correctly during unit testing.
While testing best practices generally recommend testing component
behavior rather than implementation details, mocking the
useState hook is sometimes necessary when you need to spy
on state setters directly or isolate specific state behaviors.
To mock the useState hook, you can use Jest’s
jest.spyOn method to intercept calls to
React.useState and return a mock state value along with a
mock setter function.
Step-by-Step Implementation
Suppose you have a simple Counter component that
increments a value:
// Counter.js
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default Counter;To test that clicking the button triggers the state setter, you can
mock useState in your test file as follows:
// Counter.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
describe('Counter Component', () => {
afterEach(() => {
jest.restoreAllMocks(); // Restore original implementation after each test
});
it('should call the mock state setter when the button is clicked', () => {
// 1. Create a mock function for the state setter
const setMockCount = jest.fn();
// 2. Spy on React.useState and override its return value
const useStateSpy = jest.spyOn(React, 'useState');
useStateSpy.mockImplementation((initialState) => [initialState, setMockCount]);
// 3. Render the component
render(<Counter />);
// 4. Simulate a user click event
const button = screen.getByText('Increment');
fireEvent.click(button);
// 5. Assert that the mock setter function was called
expect(setMockCount).toHaveBeenCalledTimes(1);
expect(setMockCount).toHaveBeenCalledWith(1);
});
});Key Takeaways
- Import React as an Object: In order to spy on
useState, you must import React as an entire module (i.e.,import React from 'react') in both your component and your test file. This allowsjest.spyOn(React, 'useState')to reference the method correctly. - Mock Implementation: The
mockImplementationfunction takes theinitialStateargument (in this case,0) and returns an array containing that initial state and your mock setter functionsetMockCount. - Clean Up: Always run
jest.restoreAllMocks()oruseStateSpy.mockRestore()after your tests to ensure that the realuseStatehook is restored for other test suites.