Next.js14中Vitest测试usePathname返回null的问题排查
问题原因及解决方案
核心问题分析
你遇到的usePathname返回null的问题,主要来自两个可能的原因:
- Mock写法错误:第一种mock中你错误地返回了一个函数(
vi.fn(()=>'/abc')),而非直接返回路径字符串,导致调用usePathname()得到的是一个函数而非预期的路径,最终在执行includes时因实际值不符合预期报错。 - Mock时机或上下文冲突:如果你的
vi.mock写在测试用例(it/describe)内部,Vitest的mock提升机制会导致mock不生效;另外,自定义的customRender中如果手动提供了AppRouterContext.Provider,可能会与mock的usePathname产生冲突,优先使用上下文的默认值(null)。
具体修复方案
方案1:修正Mock写法并确保全局mock
将mock代码放在测试文件最顶部(Vitest会自动提升vi.mock到模块最前),并修正usePathname的mock逻辑:
// 测试文件顶部 import { vi } from 'vitest'; // 写法1:直接返回固定路径 vi.mock('next/navigation', () => ({ usePathname: () => '/abc', useRouter: () => ({ /* 你的mockRouter内容 */ }) })); // 写法2:使用mock函数,便于后续动态修改返回值 vi.mock('next/navigation', () => ({ usePathname: vi.fn().mockReturnValue('/abc'), useRouter: () => ({ /* 你的mockRouter内容 */ }) }));
方案2:通过AppRouterContext直接注入路径(无需mock钩子)
如果mock钩子不生效,可以绕过钩子,直接在customRender的上下文提供者中传入pathname:
import { render, RenderOptions } from '@testing-library/react'; import { AppRouterContext } from 'next/dist/shared/lib/app-router-context.shared-runtime'; const customRender = (ui: React.ReactElement, options?: RenderOptions) => { return render(ui, { wrapper: ({ children }) => ( <AppRouterContext.Provider value={{ pathname: '/abc', // 补充其他必要的上下文属性 route: '/abc', params: {}, push: vi.fn(), replace: vi.fn() }} > {children} </AppRouterContext.Provider> ), ...options, }); };
这种方式直接从上下文层面提供pathname,完全避免钩子mock的问题,适合复杂的App Router测试场景。
额外注意事项
- 确保你的
Footer组件是客户端组件(顶部有'use client'指令),因为usePathname只能在客户端组件中使用,服务器组件调用该钩子本身就会抛出异常。 - 如果使用方案1的mock函数写法,后续可以在测试用例中动态修改返回值:
import { usePathname } from 'next/navigation'; it('测试不同路径的情况', () => { (usePathname as jest.Mock).mockReturnValue('/earnings'); // 执行测试逻辑 });
内容的提问来源于stack exchange,提问作者Prajwal Kulkarni
相关产品推荐
相关产品推荐

