JavaScript单元测试中Mock window.location跳转的核心是拦截assign、replace及href setter,用jest.fn()替代并验证参数;需在afterEach还原或jest.restoreAllMocks清理,Vue/React项目应优先mock路由实例而非location。

在 JavaScript 单元测试中 Mock window.location 的跳转行为,核心是**拦截并替换原生的 location.assign、location.replace 或 location.href = xxx 赋值操作**,避免真实页面跳转,同时能验证跳转目标是否符合预期。
直接覆盖 location 属性(适用于 Jest 等主流测试环境)
Jest 默认允许对全局对象属性进行可写修改。最常用、最直接的方式是在测试前 mock location.assign 和 location.replace 方法,并保存跳转参数:
- 在
beforeEach中备份原始方法(可选),然后用 jest.fn() 替换 - 注意:不能直接赋值
window.location = {...}(会报错),但可以 mock 其方法 - 示例:
beforeEach(() => {
delete window.location;
window.location = { assign: jest.fn(), replace: jest.fn() };
});
test('should redirect to /login when token expires', () => {
// 触发跳转逻辑
handleAuthFailure();
expect(window.location.assign).toHaveBeenCalledWith('/login?redirect=%2Fdashboard');
});
Mock location.href 的 setter(处理赋值跳转)
有些代码直接写 window.location.href = url,这时需 mock href 的 setter:
- 使用
Object.defineProperty重定义window.location.href,捕获赋值动作 - 配合
jest.fn()记录调用,或用变量暂存跳转地址 - 示例:
beforeEach(() => {
const originalLocation = window.location;
const hrefSetter = jest.fn();
Object.defineProperty(window, 'location', {
configurable: true,
value: {
...originalLocation,
assign: jest.fn(),
replace: jest.fn(),
set href(value) {
hrefSetter(value);
}
}
});
});
test('should set href to /home on success', () => {
performLogin();
expect(hrefSetter).toHaveBeenCalledWith('/home');
});
还原真实 location(避免测试间污染)
mock 后若不清理,可能影响后续测试。推荐在 afterEach 或 teardown 中恢复:
立即学习“Java免费学习笔记(深入)”;
- 删除 mock 后重新赋值回原生 location(Jest 中可用
globalThis.location) - 更稳妥的做法:用
jest.restoreAllMocks()(如果用了jest.spyOn) - 或者在
beforeEach开头先清理:
beforeEach(() => {
// 清理上一次 mock
delete window.location;
// 再重新定义
window.location = { assign: jest.fn(), replace: jest.fn() };
});
补充:Vue Router / React Router 场景下优先 mock 路由实例
若项目使用了 Vue Router 或 React Router,**不建议直接 mock window.location**,而应 mock 对应的路由 API:
- Vue 3 + Vue Router 4:mock
useRouter().push或router.push - React + react-router-dom v6:mock
useNavigate()返回的函数 - 这样更贴近业务逻辑,也避免耦合底层浏览器 API



















