Jest测试全局路由守卫时mock Store中getters不生效如何解决?
问题修复方案
核心原因
jest.mock写在it测试用例内部不会生效:jest的模块mock默认会被提升到模块作用域最顶部执行,写在测试用例内部的mock会晚于模块导入执行,此时路由守卫已经引用了原始的store实例,mock不会生效。- spyOn写法错误:需要基于导入的真实store实例进行方法劫持,而不是直接操作未挂载的getters对象。
修复方案1:使用顶部jest.mock(全局mock)
把mock逻辑放在所有导入语句之前,保证模块加载时就用mock的store实例:
// router/index.spec.ts // 第一步:把jest.mock放在所有import之前 jest.mock('@/store', () => ({ getters: { isLoggedIn: jest.fn(() => true) } })) // 第二步:再导入需要测试的路由守卫和store import { beforeEach } from './index' import store from '@/store' describe('test routing functionality', () => { it('should redirect to / when isLoggedIn is true and IsGuest is true', () => { const to = { matched: [{ meta: { guest: true } }], }; const next = jest.fn(); beforeEach(to, undefined, next); expect(next).toHaveBeenCalledWith('/'); }); // 不同用例需要修改返回值可以单独覆写 it('should not redirect when user is not logged in', () => { (store.getters.isLoggedIn as jest.Mock).mockReturnValue(false) const to = { matched: [{ meta: { guest: true } }], }; const next = jest.fn(); beforeEach(to, undefined, next); expect(next).not.toHaveBeenCalledWith('/'); }) })
修复方案2:使用spyOn单用例mock
如果不需要全局mockstore,可以直接在测试用例内劫持store实例的方法:
// router/index.spec.ts import { beforeEach } from './index' import store from '@/store' describe('test routing functionality', () => { it('should redirect to / when isLoggedIn is true and IsGuest is true', () => { // 基于真实store实例劫持isLoggedIn方法 const loginSpy = jest.spyOn(store.getters, 'isLoggedIn').mockReturnValue(true) const to = { matched: [{ meta: { guest: true } }], }; const next = jest.fn(); beforeEach(to, undefined, next); expect(next).toHaveBeenCalledWith('/'); // 测试结束恢复原方法避免影响其他用例 loginSpy.mockRestore() }); })
额外注意
你提供的原路由守卫代码里有一个冗余的右大括号,可能会导致逻辑执行异常,建议先修正语法问题。
内容的提问来源于stack exchange,提问作者Amir Choubani
相关产品推荐
相关产品推荐

