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

使用ts-jest与testing-library/react测试localStorage调用失败问题

解决ts-jest测试localStorage.setItem未被调用的问题

以下是针对性的测试代码调整方案,覆盖常见的问题场景:


1. 显式模拟并监听localStorage方法

Jest的jsdom环境虽自带localStorage,但测试前显式重置、监听方法能避免测试间污染,确保mock准确:

import { render, screen, fireEvent } from '@testing-library/react';
import { AuthProvider, useAuth } from './AuthProvider';

// 每个测试前重置localStorage的mock
beforeEach(() => {
  jest.spyOn(Storage.prototype, 'setItem').mockImplementation(() => {});
  jest.spyOn(Storage.prototype, 'getItem').mockImplementation(() => null);
});

// 测试后清除mock
afterEach(() => {
  jest.clearAllMocks();
});

2. 确保正确触发onLoginAction

需确认测试组件正确挂载在AuthProvider下,且按钮点击确实调用了context中的onLoginAction:

// 封装测试组件,直接绑定登录动作
const TestLoginComponent = () => {
  const { onLoginAction } = useAuth();
  const testUser = { id: 1, username: 'test_user' };
  return <button onClick={() => onLoginAction(testUser)}>Trigger Login</button>;
};

test('localStorage.setItem is called on login', () => {
  render(
    <AuthProvider>
      <TestLoginComponent />
    </AuthProvider>
  );

  // 触发登录按钮点击
  fireEvent.click(screen.getByText('Trigger Login'));

  // 验证localStorage.setItem被调用,参数匹配预期
  expect(Storage.prototype.setItem).toHaveBeenCalledWith(
    'user',
    JSON.stringify({ id: 1, username: 'test_user' })
  );
});

3. 处理异步场景的登录逻辑

如果onLoginAction包含异步操作(如API请求、异步dispatch),必须用async/await配合waitFor等待异步完成:

test('localStorage.setItem is called after async login', async () => {
  render(
    <AuthProvider>
      <TestLoginComponent />
    </AuthProvider>
  );

  fireEvent.click(screen.getByText('Trigger Login'));

  // 等待异步操作完成后验证mock
  await waitFor(() => {
    expect(Storage.prototype.setItem).toHaveBeenCalled();
  });
});

4. 适配自定义Storage封装

若AuthProvider未直接使用window.localStorage,而是封装了自定义Storage工具,需针对性mock该工具:

// 假设自定义Storage工具路径为./utils/storage
jest.mock('./utils/storage', () => ({
  setItem: jest.fn(),
  getItem: jest.fn()
}));

import { setItem } from './utils/storage';

test('custom storage setItem is called on login', () => {
  render(
    <AuthProvider>
      <TestLoginComponent />
    </AuthProvider>
  );

  fireEvent.click(screen.getByText('Trigger Login'));
  expect(setItem).toHaveBeenCalledWith('user', expect.any(String));
});

内容的提问来源于stack exchange,提问作者Jesús V.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:10:31