Hooks that consume context need a wrapper provider.
Hook Using Context
jsxconst AuthContext = createContext(null); function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within AuthProvider'); } return context; } function AuthProvider({ children }) { const [user, setUser] = useState(null); const login = async (email, password) => { const user = await authApi.login(email, password); setUser(user); }; const logout = () => setUser(null); return ( <AuthContext.Provider value={{ user, login, logout }}> {children} </AuthContext.Provider> ); }
Testing with Wrapper
jsxtest('useAuth returns user from context', () => { const wrapper = ({ children }) => ( <AuthProvider>{children}</AuthProvider> ); const { result } = renderHook(() => useAuth(), { wrapper }); expect(result.current.user).toBe(null); }); test('login updates user', async () => { const wrapper = ({ children }) => ( <AuthProvider>{children}</AuthProvider> ); const { result } = renderHook(() => useAuth(), { wrapper }); await act(async () => { await result.current.login('test@example.com', 'password'); }); expect(result.current.user).toEqual({ email: 'test@example.com' }); });
Custom Wrapper with Props
jsxfunction createWrapper(initialUser = null) { return function Wrapper({ children }) { return ( <AuthProvider initialUser={initialUser}> {children} </AuthProvider> ); }; } test('with authenticated user', () => { const mockUser = { id: '1', name: 'John' }; const wrapper = createWrapper(mockUser); const { result } = renderHook(() => useAuth(), { wrapper }); expect(result.current.user).toEqual(mockUser); });
Testing Error Cases
jsxtest('throws error when used outside provider', () => { // Suppress console.error for this test const consoleSpy = jest.spyOn(console, 'error').mockImplementation(); expect(() => { renderHook(() => useAuth()); }).toThrow('useAuth must be used within AuthProvider'); consoleSpy.mockRestore(); });
Reusable Test Utility
jsx// test-utils.js export function renderHookWithProviders(hook, options = {}) { const wrapper = ({ children }) => ( <AuthProvider> <ThemeProvider> <QueryClientProvider client={queryClient}> {children} </QueryClientProvider> </ThemeProvider> </AuthProvider> ); return renderHook(hook, { wrapper, ...options }); }