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

如何测试内部包含useAsyncStorage的React Native自定义Hook?

解决useAsyncStorage测试报错方案

错误原因

你使用的@react-native-async-storage/async-storage默认jest mock未包含useAsyncStorage钩子的实现,导致测试时提示该函数不存在。

解决方案

1. 完善AsyncStorage的Mock实现

如果项目中使用了自定义mock文件(__mocks__/@react-native-async-storage/async-storage.js),修改它以添加useAsyncStorage的实现:

// __mocks__/@react-native-async-storage/async-storage.js
import AsyncStorageMock from '@react-native-async-storage/async-storage/jest/async-storage-mock';

// 实现useAsyncStorage钩子,返回对应key的操作方法
export const useAsyncStorage = (key) => ({
  getItem: async () => AsyncStorageMock.getItem(key),
  setItem: async (value) => AsyncStorageMock.setItem(key, value),
  removeItem: async () => AsyncStorageMock.removeItem(key),
  mergeItem: async (value) => AsyncStorageMock.mergeItem(key, value),
  clear: async () => AsyncStorageMock.clear(),
  getAllKeys: async () => AsyncStorageMock.getAllKeys(),
});

export default AsyncStorageMock;

2. 修正测试文件的Mock配置

测试文件中无需指定mock的具体路径,直接mock官方包名即可,同时调整导入和测试逻辑:

import { renderHook, waitFor } from '@testing-library/react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useCustomHook } from '../path-to-your-hook'; // 替换为你的Hook实际路径

// 自动使用__mocks__下的mock文件
jest.mock('@react-native-async-storage/async-storage');

describe('Test hook', () => {
  beforeEach(async () => {
    // 清空存储,避免测试用例间数据污染
    await AsyncStorage.clear();
    await AsyncStorage.setItem('item', 'value');
  });

  it('Should return stored item', async () => {
    const { result } = renderHook(() => useCustomHook());
    
    // 等待异步存储操作完成,断言结果
    await waitFor(() => {
      expect(result.current).toBe('value');
    });
  });

  it('Should return default value when no item exists', async () => {
    await AsyncStorage.removeItem('item');
    const { result } = renderHook(() => useCustomHook());
    
    await waitFor(() => {
      expect(result.current).toBe('some value');
    });
  });
});

3. 额外优化:修复自定义Hook的重复触发问题

原Hook中useEffect依赖了state,会导致state更新后重复触发effect,可调整依赖并优化逻辑:

export const useCustomHook = () => {
  const storage = useAsyncStorage('item');
  const [state, setState] = useState<string | null>(null);

  useEffect(() => {
    // 标记组件挂载状态,避免卸载后更新state
    let isMounted = true;
    storage.getItem().then(value => {
      if (isMounted) {
        setState(value ?? 'some value');
      }
    });
    return () => {
      isMounted = false;
    };
  }, [storage]); // 移除state依赖,仅在storage实例变化时触发

  return state;
};

内容的提问来源于stack exchange,提问作者MaksimL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:37:30