React中使用Redux-Saga与fetch-mock测试路由重定向的方法
解决方案
核心思路
你当前的测试只验证了saga确实调用了redirectPos方法并传入了正确的station参数,但没有覆盖redirectPos内部的三个逻辑分支,也没有验证重定向行为是否符合预期。我们可以分两步完成测试:先单独单元测试redirectPos的分支逻辑,再补全saga流程的分支覆盖。
步骤1:测试redirectPos函数逻辑
首先将原文件中的redirectPos函数导出,方便测试文件引入。之后对两个全局依赖做mock:window.location.href和sagamore.router.redirect,示例测试代码如下:
// 从saga源文件引入redirectPos import { redirectPos } from './stationSagas' // 全局mock sagamore对象 global.sagamore = { router: { redirect: jest.fn() } } describe('redirectPos 分支测试', () => { afterEach(() => { // 每次测试后重置mock调用记录和location jest.clearAllMocks() delete window.location window.location = new URL('http://test.local') }) it('当前路径含pos且station存在cash_drawer时,重定向到pos', () => { window.location.href = 'http://test.local/pos/order' const testStation = { cash_drawer: { id: 2 } } redirectPos(testStation) expect(sagamore.router.redirect).toHaveBeenCalledWith('pos') }) it('station无cash_drawer时,重定向到sales/dashboard', () => { window.location.href = 'http://test.local/any/path' const testStation = { cash_drawer: null } redirectPos(testStation) expect(sagamore.router.redirect).toHaveBeenCalledWith('sales/dashboard') }) it('其他场景不触发重定向', () => { window.location.href = 'http://test.local/setting' const testStation = { cash_drawer: { id: 2 } } redirectPos(testStation) expect(sagamore.router.redirect).not.toHaveBeenCalled() }) })
步骤2:补全saga流程的测试覆盖
你当前的saga测试只覆盖了station存在cash_drawer的场景,需要补充不同入参的测试用例,验证不同场景下saga都会正确调用redirectPos:
- 新增station无cash_drawer的测试用例,其余接口mock逻辑和现有用例一致,只需要修改mock返回的station对象的
cash_drawer为null,最后同样验证call(redirectPos, 无cash_drawer的station)调用正确即可。
如果需要做集成验证,也可以在saga执行到call(redirectPos)之后,继续执行saga.next()触发函数执行,直接验证redirect方法的调用:
// 现有测试用例末尾补充 // 触发redirectPos执行 saga.next() // 验证重定向行为符合预期 expect(sagamore.router.redirect).toHaveBeenCalledWith('pos')
注意事项
- 测试中修改
window.location.href不要直接赋值,用delete window.location后重新赋值为new URL实例的方式模拟,避免浏览器环境的只读属性报错。 - 所有外部依赖(如
sagamore)都要用mock实现,不要引入真实业务逻辑,避免测试结果被外部逻辑影响。
内容的提问来源于stack exchange,提问作者Mitchell Alton
相关产品推荐
相关产品推荐

