如何正确测试依赖useWindowSize的useSidebarWidth自定义Hook?
问题分析
你遇到的 TypeError: (0 , _hooks.useSidebarWidth) is not a function 错误,根源在于你通过 jest.mock('hooks', ...) 完全替换了整个 hooks 模块的导出,但只提供了 useWindowSize 的 mock 实现,没有保留真实的 useSidebarWidth 函数。因此测试代码中导入的 useSidebarWidth 变成了 undefined,导致调用失败。
解决方案
正确的做法是只 mock useWindowSize,同时保留 useSidebarWidth 的真实实现。可以通过 jest.requireActual 获取模块的原始导出,再覆盖需要 mock 的部分。
修正后的测试代码
import { renderHook } from '@testing-library/react-hooks'; import { useSidebarWidth, useWindowSize } from 'hooks'; // 仅 mock useWindowSize,保留其他 hook 的真实实现 jest.mock('hooks', () => ({ ...jest.requireActual('hooks'), useWindowSize: jest.fn(), })); describe('useSidebarWidth', () => { // 每次测试前重置 mock,避免测试间污染 beforeEach(() => { jest.clearAllMocks(); }); it('窗口宽度小于1440px时,返回72px作为侧边栏宽度', () => { // 设置 mock 返回值 (useWindowSize as jest.Mock).mockReturnValue({ width: 700 }); const { result } = renderHook(() => useSidebarWidth()); expect(result.current.sidebarWidth).toBe('72px'); expect(result.current.isExpanded).toBe(false); }); it('窗口宽度大于1440px时,返回248px作为侧边栏宽度', () => { (useWindowSize as jest.Mock).mockReturnValue({ width: 1500 }); const { result } = renderHook(() => useSidebarWidth()); expect(result.current.sidebarWidth).toBe('248px'); expect(result.current.isExpanded).toBe(true); }); });
关键说明
jest.requireActual的作用:获取hooks模块的原始导出,确保useSidebarWidth是真实可用的函数。- mock 重置:通过
beforeEach中的jest.clearAllMocks()清空 mock 的调用记录和返回值,避免不同测试用例之间的干扰。 - 类型断言:由于 TypeScript 无法识别 mock 后的函数类型,需要用
(useWindowSize as jest.Mock)进行类型断言,才能调用mockReturnValue方法。
内容的提问来源于stack exchange,提问作者Pierre Olivier Tran
相关产品推荐
相关产品推荐

