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

如何对React的useContext Hook进行Mock/Spy测试?

问题:测试依赖useContext的辅助函数失败

我正在尝试对两个导出的辅助函数做单元测试,这两个函数都通过useContext调用默认上下文值,但查了很多资料还是没法成功实现。

原函数代码

export const func1 = () => {
    const { key1, key2 } = useContext(MyContext);
    return { key1, key2 };
}

export const func2 = () => {
    const { key2 } = useContext(MyContext);

    // some more complex stuff here
}

原测试代码及报错

import React, { useContext } from 'react';

...

it('with mock', () => {
    jest.mock('react', () => ({
      ...jest.requireActual('react'),
      useContext: (ctx: any) => mockUseContext(ctx)
    }));

    useContext.mockImplementation(ctx => ({ someKey: 'someVal' }));

    // 报错:Property 'mockImplementation' does not exist on type ' (context: Context ) => T

    expect(func1()).toBe({ someKey: 'someVal' });
});

it('with spyOn', () => {
     jest.spyOn(React, 'useContext').mockImplementation(() => ({ someKey: 'someVal' }));

     expect(func1()).toBe({ someKey: 'someVal' });
});

解决方法

1. 修正jest.mock的使用方式

jest.mock必须放在模块作用域(测试文件顶部),不能嵌套在测试用例里。同时要通过类型断言让TypeScript识别这是个mock函数:

import React, { useContext } from 'react';
import { func1, func2 } from './your-file-path';
import { MyContext } from './your-context-path';

// 全局mock React的useContext
jest.mock('react', () => ({
  ...jest.requireActual('react'),
  useContext: jest.fn()
}));

// 类型断言解决TS类型错误
const mockUseContext = useContext as jest.Mock;

it('func1 should return context values', () => {
  // 模拟上下文返回值
  mockUseContext.mockReturnValue({ key1: 'test1', key2: 'test2' });
  
  // 注意:对象比较要用toEqual,toBe是比较引用地址,会失败
  expect(func1()).toEqual({ key1: 'test1', key2: 'test2' });
});

2. spyOn的正确用法

如果用spyOn,记得测试结束后恢复mock,避免影响其他测试用例:

it('func2 should use context key2', () => {
  const mockContext = { key2: 'test-key2' };
  const spy = jest.spyOn(React, 'useContext').mockReturnValue(mockContext);
  
  // 执行func2并根据逻辑添加断言
  func2();
  // 验证useContext是否传入了正确的上下文对象
  expect(spy).toHaveBeenCalledWith(MyContext);
  
  // 清除mock,还原原函数
  spy.mockRestore();
});

3. 核心注意点

  • 对象比较用toEqual:toBe比较的是对象引用,测试对象内容必须用toEqual。
  • TypeScript类型处理:必须把useContext断言为jest.Mock,否则会出现类型错误。
  • mock作用域控制:jest.mock是模块级别的,会影响整个测试文件;spyOn可以针对单个用例,用完记得恢复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:25:09