Jest中测试页面加载URL读取函数:设置window.location遇阻的解决方案求助
解决Jest测试中修改window.location的问题
我完全懂你现在的困扰——在测试页面加载时读取URL的功能时,直接操作window.location总会抛出Not implemented: navigation (except hash changes)的错误,mock了assign方法又没法同步更新href,试了各种办法都不行,确实挺闹心的。
下面给你两个可行的解决方案,能同时满足assign被正确调用且href同步更新的需求:
方案一:自定义带getter/setter的mock Location对象
这个方法手动实现href的读写逻辑,让assign调用时自动更新href:
test('Correct load-state', () => { // 保存原始的location,方便测试后恢复 const originalLocation = window.location; let currentHref = window.location.href; const mockLocation = { // 用getter返回当前href get href() { return currentHref; }, // 用setter更新href值 set href(newHref) { currentHref = newHref; }, // 让assign方法内部调用href的setter assign: jest.fn(function(url) { this.href = url; }) }; // 替换window.location Object.defineProperty(window, 'location', { value: mockLocation, writable: true }); // 测试逻辑 window.location.assign('/about'); // 断言assign被正确调用 expect(mockLocation.assign).toHaveBeenCalledWith('/about'); // 断言href已更新 expect(window.location.href).toBe('/about'); // 测试直接修改href window.location.href = '/contact'; expect(window.location.href).toBe('/contact'); // 测试后恢复原始location afterEach(() => { Object.defineProperty(window, 'location', { value: originalLocation, writable: false }); }); });
方案二:利用URL对象模拟Location
URL对象本身就包含href、pathname、search等和Location一致的属性,用它来模拟会更接近真实环境,还能自动处理相对路径:
test('Correct load-state', () => { const originalLocation = window.location; // 创建一个URL对象,初始路径设为你需要测试的路径 const mockUrl = new URL('/about', window.location.origin); // 给URL对象添加assign方法,调用时更新href mockUrl.assign = jest.fn(function(url) { this.href = new URL(url, this.origin).href; }); // 替换window.location Object.defineProperty(window, 'location', { value: mockUrl, writable: true }); // 测试调用assign window.location.assign('/products'); expect(mockUrl.assign).toHaveBeenCalledWith('/products'); // 此时href会是完整的URL,比如"http://localhost/products" expect(window.location.href).toBe(`${window.location.origin}/products`); // 还能直接用pathname等属性 expect(window.location.pathname).toBe('/products'); // 测试后恢复 afterEach(() => { Object.defineProperty(window, 'location', { value: originalLocation, writable: false }); }); });
为什么之前的方法无效?
你之前的mock对象里,href是一个固定的初始值,assign方法只是被调用,但没有修改href的逻辑,所以自然不会更新。上面的两种方案都给href加上了可更新的逻辑,同时让assign方法能触发这个更新,完美解决了你的问题。
内容的提问来源于stack exchange,提问作者Dan Knights
相关产品推荐
相关产品推荐

