在Cypress中模拟Next.js App Router的useRouter钩子遇错求助
解决Cypress测试Next.js App Router useRouter挂载错误的方案
核心问题
你遇到的错误根源是:Next.js App Router的useRouter来自next/navigation模块,而非Pages Router的next/router,直接套用Cypress文档里的Pages Router stub方案自然无效;且mock时未正确定位到next/navigation模块,导致出现"stub property 'useRouter' of undefined"错误。
具体解决步骤
1. 正确Mock next/navigation的useRouter
在Cypress测试文件中,于组件挂载前添加mock逻辑,模拟useRouter返回组件所需的路由方法:
beforeEach(() => { // Mock next/navigation模块的useRouter cy.stub(require('next/navigation'), 'useRouter').returns({ push: cy.stub().as('pushRoute'), // 存根push方法,方便后续断言 replace: cy.stub(), back: cy.stub() // 组件中用到的其他路由方法都需要在这里模拟 }); });
2. 挂载组件并验证逻辑
完成mock后正常挂载组件,可对路由方法的调用进行断言:
it('renders ForgotPassword component and triggers route push', () => { cy.mount(<ForgotPassword />); // 触发组件内的跳转逻辑 cy.get('[data-testid="submit-btn"]').click(); // 断言路由push方法被正确调用 cy.get('@pushRoute').should('have.been.calledWith', '/reset-password'); });
3. 备选全局Mock方案
若模块mock方式无效,可尝试全局mocknext/navigation:
beforeEach(() => { cy.window().then((win) => { win.next = { navigation: { useRouter: () => ({ push: cy.stub().as('pushRoute') }) } }; }); });
关键注意事项
- 确认组件中
useRouter的导入路径为import { useRouter } from 'next/navigation',而非next/router - 仅需模拟组件实际用到的路由方法(比如组件只用了
push,就无需模拟其他方法) - 若使用TypeScript,可添加全局类型声明避免类型报错:
declare global { interface Window { next: { navigation: { useRouter: () => { push: (path: string) => void; }; }; }; } }
内容的提问来源于stack exchange,提问作者Innocent Victor Mark
相关产品推荐
相关产品推荐

