使用Jasmine和JS测试localStorage时无法访问键值对的问题
问题原因及解决办法
核心问题
你用spyOn(window.localStorage, 'setItem')时,Jasmine默认只会监听这个方法的调用情况,不会执行它的原生存储逻辑——说白了就是你以为存进去的键值对,实际上根本没写到localStorage里,遍历自然找不到。Jasmine的默认spy会把原方法替换成空函数,只记录调用次数和参数,不干活。
两种解决思路
1. 让spy保留原生功能
如果既要监听调用,又要让setItem真的存数据,给spy加上callThrough()就行:
spyOn(window.localStorage, 'setItem').and.callThrough();
这样testSet调用setItem时,Jasmine会记录调用信息,同时原生的存储逻辑也会执行,后续遍历就能找到testSet这个键了。
2. 手动模拟localStorage(更推荐用于隔离测试)
要是不想依赖真实的localStorage(防止测试用例之间互相干扰),可以自己造个模拟对象替换掉它:
let mockStorage = {}; beforeEach(() => { mockStorage = {}; // 模拟setItem spyOn(window.localStorage, 'setItem').and.callFake((key, val) => { mockStorage[key] = val; }); // 模拟getItem spyOn(window.localStorage, 'getItem').and.callFake(key => mockStorage[key] || null); // 模拟遍历需要的key()方法和length属性 spyOn(window.localStorage, 'key').and.callFake(index => Object.keys(mockStorage)[index]); Object.defineProperty(window.localStorage, 'length', { get: () => Object.keys(mockStorage).length }); });
这样testDeletePrefix遍历localStorage时,就能通过模拟的方法拿到你存的键,同时还能正常验证setItem的调用情况。
收尾注意
测试完记得清理状态,避免影响其他用例:
afterEach(() => { window.localStorage.clear(); // 或者重置模拟对象 mockStorage = {}; });
内容的提问来源于stack exchange,提问作者Richlewis
相关产品推荐
相关产品推荐

