You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript单元测试中使用Jest模拟localStorage

如何在TypeScript单元测试中使用Jest模拟localStorage

我之前在TypeScript项目里用Jest模拟localStorage时,也遇到过一模一样的“ReferenceError: localStorage is not defined”报错,折腾了好一阵才搞定。结合你的需求(只需要模拟getItem和removeItem),给你分享两个亲测有效的方法:

方法一:单个测试文件内模拟(适合局部测试)

首先要解决TypeScript的类型问题,因为Node环境下默认没有window/localStorage的类型定义,我们需要先扩展全局类型,不然会报类型错误。在测试文件顶部加上这段:

// 扩展全局类型,让TypeScript识别localStorage
declare module NodeJS {
  interface Global {
    localStorage: Storage;
  }
}

然后定义我们的mock对象,只实现你需要的getItem和removeItem,其他方法如果TypeScript要求的话,可以空实现:

const mockLocalStorage = {
  getItem: jest.fn(),
  removeItem: jest.fn(),
  // 下面这几个是Storage接口要求的必选属性/method,空实现即可
  setItem: jest.fn(),
  clear: jest.fn(),
  key: jest.fn(),
  length: 0
};

接下来在测试开始前,把这个mock挂载到全局对象上,并且每个测试前清空mock的调用记录:

beforeEach(() => {
  jest.clearAllMocks(); // 每次测试前重置mock
  Object.defineProperty(global, 'localStorage', {
    value: mockLocalStorage,
  });
});

现在就可以正常写测试了,举个例子:

// 假设你要测试的函数是这个
function getStoredUser() {
  return localStorage.getItem('user');
}

test('getStoredUser能正确获取localStorage的值', () => {
  // 预设getItem的返回值
  mockLocalStorage.getItem.mockReturnValue('{"name": "Guerlain"}');
  
  const result = getStoredUser();
  
  // 断言getItem被正确调用
  expect(mockLocalStorage.getItem).toHaveBeenCalledWith('user');
  // 断言返回值正确
  expect(result).toBe('{"name": "Guerlain"}');
});

方法二:全局配置(所有测试文件通用)

如果你的很多测试都需要用到localStorage的mock,每次写一遍太麻烦,可以在Jest的全局setup文件里配置一次,所有测试都能用。

  1. 首先在项目里创建一个setup文件,比如src/setupTests.ts,内容和方法一类似:
declare module NodeJS {
  interface Global {
    localStorage: Storage;
  }
}

const mockLocalStorage = {
  getItem: jest.fn(),
  removeItem: jest.fn(),
  setItem: jest.fn(),
  clear: jest.fn(),
  key: jest.fn(),
  length: 0
};

global.localStorage = mockLocalStorage;

// 全局钩子:每个测试前清空mock
beforeEach(() => {
  jest.clearAllMocks();
});
  1. 然后在Jest的配置文件(比如jest.config.ts)里指定这个setup文件:
export default {
  // 其他配置...
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
};

这样所有测试文件里都能直接使用localStorage的mock了,不用再重复写类型扩展和挂载代码。

为什么你之前的方法没生效?

你之前尝试用jest.mock('localStorage', ...)是不对的,因为localStorage是浏览器环境的全局对象,不是一个可以用import导入的模块,所以Jest找不到这个模块,自然mock失败。正确的做法是直接把mock挂载到global对象上,模拟浏览器的全局环境。

备注:内容来源于stack exchange,提问作者Guerlain BLANCHARD guerlblanch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 07:09:33