前端单元测试中 mock localstorage 和 document.cookie 的核心是替换或拦截浏览器原生 api 行为,需完整模拟方法并维护内存状态,且须在 beforeeach 重置、aftereach 清空以避免污染。

在前端单元测试中 Mock localStorage 和 document.cookie,核心是**替换或拦截浏览器原生 API 的行为**,使其可控、可断言、不依赖真实环境。下面分两部分说明常用且可靠的做法。
Mock localStorage
localStorage 是全局对象,测试前需手动模拟其方法(setItem、getItem、removeItem、clear),并维护一个内存中的键值对映射。推荐在每个测试用例前重置状态,避免污染。
- 使用 Jest 时,可在
beforeEach中定义 mock:
const localStorageMock = {
store: {},
getItem(key) { return this.store[key] ?? null; },
setItem(key, value) { this.store[key] = String(value); },
removeItem(key) { delete this.store[key]; },
clear() { this.store = {}; }
};
beforeEach(() => {
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
});
- 若使用 Vitest,可用
vi.stubGlobal或直接赋值:window.localStorage = localStorageMock; - 注意:不能只 mock 单个方法(如只 mock
setItem),否则其他方法仍调用原生实现,可能报错或行为不一致。
Mock document.cookie
document.cookie 是一个特殊的 getter/setter 属性,不能直接赋值覆盖。必须通过 Object.defineProperty 拦截读写行为,并自行维护 cookie 字符串。
- 基础 mock 示例(支持简单 key=value 格式):
const cookieStore = {};
const mockCookieDescriptor = {
get() { return Object.entries(cookieStore)
.map(([k, v]) => `${k}=${v}`)
.join('; '); },
set(str) {
str.split(';').forEach(pair => {
const [key, ...rest] = pair.trim().split('=');
if (key) cookieStore[key] = rest.join('=');
});
}
};
beforeEach(() => {
Object.defineProperty(document, 'cookie', mockCookieDescriptor);
});
- 该 mock 支持基本的读写,但不处理过期时间、路径、域名等属性——单元测试中通常无需模拟这些细节;
- 如需更完整行为(如自动清除过期 cookie),可引入轻量库如
jsdom-cookies(仅限 jsdom 环境); - 务必在
afterEach清空cookieStore,防止测试间干扰。
实际测试中注意事项
Mock 后要验证逻辑是否按预期调用存储 API,而不是只检查结果状态。
- 用
jest.fn()包装setItem或cookie setter,然后用expect(fn).toHaveBeenCalledWith(...)断言调用参数; - 避免在测试中直接访问
window.localStorage或document.cookie做断言——应通过被测函数的副作用来间接验证; - 若使用类库封装了存储操作(如
StorageService),优先 mock 该服务本身,而非底层 API,更符合测试隔离原则。
工具辅助(可选)
有现成工具简化流程,适合中大型项目:
-
jest-localstorage-mock:Jest 插件,一行启用完整 localStorage mock; -
jsdom-cookies:为 jsdom 提供更贴近浏览器的 cookie 行为; - Vitest 用户可封装自定义
setupTests.ts统一注入 mock,避免重复代码。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











