如何使用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
相关产品推荐
相关产品推荐

