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

Vitest运行React测试时出现Cannot read properties of undefined错误排查

解决Vitest测试中React-Query+useImmer的随机undefined错误

针对你遇到的测试中activeData.section/activeData.page随机变为undefined、导致Cannot read properties of undefined (reading 'name')的问题,从以下几个方向排查和解决:

1. 检查useImmer的状态更新逻辑,避免深层属性被意外覆盖

如果组件中存在监听react-query返回数据并更新activeData的逻辑,不要直接替换整个activeData对象,否则一旦mock数据出现异常(哪怕概率极低)或者时序问题,就会覆盖useImmer初始化的完整结构。

错误示例:

const [activeData, setActiveData] = useImmer({ notebook: {}, section: {}, page: {} });
const { data } = useQuery('your-query-key', fetchData);

useEffect(() => {
  if (data) {
    // 直接替换会丢失未在data中定义的属性,或者data结构不完整时覆盖为undefined
    setActiveData(data);
  }
}, [data]);

正确做法:用immer的produce做深层合并,只更新需要的属性:

useEffect(() => {
  if (data) {
    setActiveData(draft => {
      draft.notebook = { ...draft.notebook, ...data.notebook };
      draft.section = { ...draft.section, ...data.section };
      draft.page = { ...draft.page, ...data.page };
    });
  }
}, [data]);

2. 强制稳定测试中的React-Query异步时序

Vitest中React-Query的异步加载时序可能和浏览器不一致,需要确保测试等待查询完全完成后再断言:

  • 初始化QueryClient时关闭重试和自动重取,避免测试中状态波动:
    const queryClient = new QueryClient({
      defaultOptions: {
        queries: {
          retry: false,
          refetchOnWindowFocus: false,
          refetchOnMount: false,
        },
      },
    });
    
  • 测试中用queryClient.ensureQueryData替代单纯的waitFor,确保查询数据已就绪:
    test('组件渲染正常', async () => {
      render(<YourComponent />, { wrapper: QueryClientProviderWrapper });
      // 等待查询完成并返回数据
      await queryClient.ensureQueryData(['your-query-key']);
      // 再执行断言
      expect(screen.getByRole('textbox')).toHaveValue('预期的页面名称');
    });
    

3. 验证MSW Mock的稳定性

虽然你说mock返回完整数据,但测试中的异步mock可能存在偶发的结构缺失,建议在mock handler中硬编码完整的返回结构,避免动态生成导致的意外:

rest.get('/api/your-data', (req, res, ctx) => {
  // 硬编码完整结构,确保每次返回的data都包含notebook/section/page
  return res(ctx.json({
    notebook: { id: '1', name: '测试笔记本' },
    section: { id: '1', name: '测试章节' },
    page: { id: '1', name: '测试页面' },
  }));
});

4. 添加防御性编程,避免运行时错误

即使测试问题解决,为了代码健壮性,在JSX中添加可选链和空值合并操作符,避免线上环境出现类似问题:

value={activeData.page?.name ?? ''}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:12:26