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

如何使用Jest监视函数组件内部未导出的函数?

如何使用Jest监视函数组件内部未导出的函数?

组件代码如下:

const ProfilePage: NextPage<Props> = () => {
  const getUser = () => {
    return {
      name: 'Joker',
    };
  };
  return (
    <Box>Hello world</Box>
  );
};

需求:监视getUser函数,验证它是否返回{name: 'Joker'}。曾尝试使用Enzyme,但React 18版本不支持该工具,无法生效。

之前的测试代码及报错:

it('GetUserSpy', () => {
  jest.spyOn(ProfilePage.prototype,'getUser') // 报错:prototype is undefined,因为函数组件没有prototype属性
});

解决方案

函数组件内部的未导出函数属于组件函数的局部作用域(闭包),外部无法直接访问或监视,因此需要通过以下方式处理:

1. 将内部函数提取为独立导出的模块函数

这是最直接的方案,把getUser移到单独的工具模块中,这样就能通过Jest轻松监视它。

步骤1:提取函数到外部模块
创建userUtils.ts:

export const getUser = () => {
  return { name: 'Joker' };
};

步骤2:修改组件导入使用该函数

import { getUser } from './userUtils';

const ProfilePage: NextPage<Props> = () => {
  // 组件逻辑中可直接调用getUser
  return <Box>Hello world</Box>;
};

步骤3:编写测试代码

import { getUser } from './userUtils';
import ProfilePage from './ProfilePage';

// 模拟整个工具模块
jest.mock('./userUtils');

it('验证getUser返回正确值', () => {
  // 指定模拟函数的返回值
  (getUser as jest.Mock).mockReturnValue({ name: 'Joker' });
  
  // 直接调用函数验证结果
  expect(getUser()).toEqual({ name: 'Joker' });

  // 如果组件中调用了getUser,也可以渲染组件并验证相关行为
  // render(<ProfilePage />);
  // 后续断言组件基于getUser返回值的表现
});

2. 通过组件行为间接验证函数逻辑

如果不想提取函数,且getUser的返回值会影响组件的行为(比如渲染内容、触发副作用),可以通过测试组件的外部表现来间接验证getUser的正确性。

修改组件(添加调用场景)

const ProfilePage: NextPage<Props> = () => {
  const getUser = () => {
    return { name: 'Joker' };
  };

  const [userName, setUserName] = useState('');

  const handleLoadUser = () => {
    const user = getUser();
    setUserName(user.name);
  };

  return (
    <Box>
      <button onClick={handleLoadUser}>加载用户</button>
      <div data-testid="user-name">{userName}</div>
    </Box>
  );
};

测试代码

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

it('加载用户时getUser返回正确的用户名', () => {
  render(<ProfilePage />);
  
  // 触发调用getUser的操作
  fireEvent.click(screen.getByText('加载用户'));
  
  // 验证组件表现是否符合预期
  expect(screen.getByTestId('user-name')).toHaveTextContent('Joker');
});

为什么原方法不生效?

函数组件是普通的JavaScript函数,不存在prototype属性,而jest.spyOn针对原型的方式仅适用于类组件的类方法,因此原代码会报错。同时,组件内部的局部函数无法被外部作用域访问,自然无法直接监视。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 10:42:31