如何使用Jest测试含useEffect请求的React组件?
如何Mock请求让React组件的fetchedEmbed状态与mockModel相等?
要实现这个需求,我们可以用Jest配合React Testing Library来Mock全局的fetch函数,让它返回预设的mockModel数据,从而触发组件更新fetchedEmbed状态。以下是具体步骤和代码示例:
1. 准备测试环境
确保项目已安装jest、@testing-library/react、@testing-library/jest-dom这些基础测试依赖。
2. Mock全局fetch函数
在测试文件中覆盖全局fetch,让它返回包含mockModel的模拟响应:
import React from 'react'; import { render, waitFor } from '@testing-library/react'; import Embed from './Embed'; import { mockModel } from './your-file-path'; // 导入你的mockModel对象 // 每次测试前初始化Mock beforeEach(() => { global.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve(mockModel), ok: true, }) ) as jest.Mock; }); // 测试后清理Mock,避免污染其他用例 afterEach(() => { jest.restoreAllMocks(); });
3. 编写测试用例验证状态
可以通过两种方式验证fetchedEmbed是否与mockModel一致:
方式一:直接监控状态更新函数
通过MockuseState来捕获setFetchedEmbed的调用参数:
test('组件挂载后fetchedEmbed与mockModel完全匹配', async () => { // Mock useState,捕获状态更新函数 const mockSetFetchedEmbed = jest.fn(); jest.spyOn(React, 'useState').mockImplementation(() => [undefined, mockSetFetchedEmbed]); // 渲染组件,传入符合StorylineEmbedType的测试数据 render(<Embed model={{ /* 你的测试用model数据 */ }} />); // 等待请求完成和状态更新 await waitFor(() => { expect(mockSetFetchedEmbed).toHaveBeenCalledWith(mockModel); }); });
方式二:通过渲染结果反向验证状态
组件会根据fetchedEmbed渲染对应HTML,我们可以验证渲染内容是否匹配mockModel的html字段:
test('组件渲染mockModel对应的嵌入内容', async () => { render(<Embed model={{ /* 你的测试用model数据 */ }} />); // 等待加载状态消失 await waitFor(() => { expect(screen.queryByClassName('loading')).not.toBeInTheDocument(); }); // 验证渲染的DOM元素属性是否与mockModel一致 const widgetDiv = screen.getByClassName('opinary-widget-embed'); expect(widgetDiv).toHaveAttribute('data-poll', 'berlegen-sie-eine-wrmepumpe-einzubauen_r'); expect(widgetDiv).toHaveAttribute('data-customer', 'rtl'); });
注意事项
- 类型匹配:当前
OembedResponse类型仅包含html、width、height,而mockModel有额外字段。若要消除TypeScript警告,可以扩展OembedResponse类型,或在测试中用类型断言:mockModel as OembedResponse。 - useEffect执行逻辑:组件的
useEffect依赖为空数组,只会在挂载时执行一次请求,测试无需处理依赖更新场景。
内容的提问来源于stack exchange,提问作者Konstantinos Alexis
相关产品推荐
相关产品推荐

