When using Jest for unit testing, if our components depend on state variables provided by context, we need to ensure that these state variables are properly mocked in the test environment. Here, I'll demonstrate with a concrete example how to mock a single state variable within a React context.
Step 1: Create the Context
First, we create a ThemeContext.
javascriptimport React, { createContext, useState, useContext } from 'react'; const ThemeContext = createContext(); export function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); } export function useTheme() { return useContext(ThemeContext); }
Step 2: Write the Component
Assume we have a simple component that depends on ThemeContext.
javascriptimport React from 'react'; import { useTheme } from './ThemeContext'; function Greeting() { const { theme } = useTheme(); return <h1 className={theme}>Hello, world!</h1>; } export default Greeting;
Step 3: Mock the Context for Testing
When testing the Greeting component, we can mock ThemeContext using Jest and @testing-library/react.
javascriptimport React from 'react'; import { render } from '@testing-library/react'; import Greeting from './Greeting'; import { ThemeContext } from './ThemeContext'; test('Greeting component receives theme', () => { // Set our mocked context value const themeValue = { theme: 'dark' }; // Mock the `useContext` hook using Jest's `mockImplementation` method jest.spyOn(React, 'useContext').mockImplementation(() => themeValue); const { getByText } = render(<Greeting />); expect(getByText('Hello, world!')).toHaveClass('dark'); });
In this test, we intercept the call to React.useContext using jest.spyOn to ensure it returns our predefined themeValue. This guarantees that regardless of how useTheme invokes useContext, it receives the theme value we've configured for testing purposes.
The advantage of this approach is that we can precisely control the values within the context without rendering the provider component, resulting in faster tests that are isolated from other state changes. This is highly applicable for unit testing.