如何用Jest和Enzyme模拟React函数组件中的fetchResults方法
看起来你遇到的问题是没法mock组件内部的fetchResults函数——这很正常,因为它是HomePage函数组件里的私有函数,你之前尝试直接mock整个组件模块的方式根本碰不到它。咱们换个思路,从它依赖的外部方法入手来解决:
首先,先分析你的代码:fetchResults其实是封装了Adaptor.fetch()的调用,所以与其mock内部的fetchResults,不如直接mock外部的Adaptor.fetch,这样更简单也更符合测试最佳实践。
解决方案一:Mock外部依赖Adaptor.fetch
假设你的Adaptor是从某个模块(比如../adaptor)导入的,你可以用Jest直接mock这个模块:
// 在你的测试文件顶部 import { Adaptor } from '../adaptor'; // Mock整个Adaptor模块,让fetch方法返回模拟的已解析Promise jest.mock('../adaptor', () => ({ fetch: jest.fn().mockResolvedValue({ data: [{ value: 'test' }] }), }));
这样当你的组件调用fetchResults()时,它内部的Adaptor.fetch()会返回你预设的模拟数据,fetchResults的Promise自然就会解析成这个值。
为什么你之前的方法无效?
你之前尝试mock../components/homePage模块,返回一个包含fetchResults的对象,但这个模块实际导出的是HomePage组件,而不是fetchResults函数——fetchResults是组件内部的私有函数,根本不在模块的导出列表里,所以你的mock完全没作用。
额外优化:简化你的fetchResults函数
顺便提一句,你当前的fetchResults写法有点冗余,没必要手动包一层新的Promise,直接返回Adaptor.fetch()的结果就行(前提是Adaptor.fetch本身返回Promise):
const fetchResults = () => { return Adaptor.fetch(); // 直接返回外部方法的Promise }
完整测试用例示例
结合React Testing Library,你的测试可以这样写:
import { render, waitFor } from '@testing-library/react'; import { HomePage } from '../components/homePage'; import { Adaptor } from '../adaptor'; jest.mock('../adaptor', () => ({ fetch: jest.fn().mockResolvedValue({ data: [{ value: 'test' }] }), })); test('HomePage loads and displays mock data', async () => { const { getByText } = render(<HomePage />); // 等待组件完成数据获取和渲染 await waitFor(() => { // 这里根据你的<Content>组件实际渲染的内容调整断言 expect(getByText('test')).toBeInTheDocument(); }); // 验证Adaptor.fetch确实被调用了 expect(Adaptor.fetch).toHaveBeenCalledTimes(1); });
这样就能完美模拟数据请求,验证组件的行为了。
内容的提问来源于stack exchange,提问作者Sarun UK

