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

使用Jest/Enzyme测试React useContext组件时如何给state赋值并解决报错

报错原因

直接渲染Timer组件时,组件外层没有提供GameContext的上下文实例,useContext(GameContext)返回值为undefined,尝试解构timer属性就会触发该报错。

解决方案

你可以通过以下两种方式给组件注入需要的context状态:


方案1:使用GameContext.Provider包裹待测组件

该方案更贴近组件实际运行场景,无需修改组件依赖,测试代码示例如下:

import { shallow } from 'enzyme';
import React from 'react';
import Timer from './timer';
import { GameContext } from './global/contexts';

// 自定义模拟的context值,包含timer和mock的setTimer方法
const mockContext = {
  timer: 2000,
  setTimer: jest.fn()
};

test('Timer组件正常渲染计时数值', () => {
  const wrapper = shallow(
    <GameContext.Provider value={mockContext}>
      <Timer />
    </GameContext.Provider>
  );
  // 调用dive()获取Timer组件本身的渲染内容(shallow默认只渲染第一层Provider)
  const timerDom = wrapper.dive().find('[data-testid="timer"]');
  // 2000 / 100 = 20,所以显示Timer : 20
  expect(timerDom.text()).toBe('Timer : 20');
});

方案2:直接mockuseContext返回值

该方案无需包裹Provider,适合单组件独立测试场景,代码示例如下:

import { shallow } from 'enzyme';
import React from 'react';
import Timer from './timer';

const mockSetTimer = jest.fn();
// 全局mock React的useContext方法,返回自定义的状态
jest.spyOn(React, 'useContext').mockReturnValue({
  timer: 3000,
  setTimer: mockSetTimer
});

test('Timer组件倒计时逻辑正常', () => {
  // 启用假定时器,不需要等待真实计时
  jest.useFakeTimers();
  const wrapper = shallow(<Timer />);
  // 快进1000ms,对应100次10ms的定时器触发
  jest.advanceTimersByTime(1000);
  // 验证setTimer被调用了100次
  expect(mockSetTimer).toHaveBeenCalledTimes(100);
  // 测试结束后恢复真实定时器
  jest.useRealTimers();
});

// 每次测试结束后清除mock,避免影响其他用例
afterEach(() => {
  jest.clearAllMocks();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 05:36:08