如何渲染并测试接入Mock API的React组件
问题根因
你的测试无法完成组件渲染层校验,是几个写法错误导致的:
- 导入了无关的Mock方法:你从
__mocks__目录引入的fetchWeatherData是独立于组件的外部函数,手动调用它不会触发Weather组件内部的state更新。实际上组件挂载时已经通过useEffect自动执行了内部定义的请求逻辑,根本不需要在测试用例里手动触发请求。 waitFor使用方式错误:该API的作用是轮询执行回调直到断言通过,你把请求调用放在回调内部,会导致每次轮询都重复触发请求,极易出现测试不稳定的问题。- 注释掉了Mock重置逻辑:
afterEach中的jest.resetAllMocks()被注释后,不同测试用例之间的Mock状态会互相污染,导致测试结果不可预期。
修正后的测试代码
import axios from 'axios'; import { render, screen } from '@testing-library/react'; import Weather from '../Weather'; jest.mock('axios'); const mockedAxios = axios as jest.Mocked<typeof axios>; describe('天气组件API Mock测试', () => { afterEach(() => { // 每个用例跑完重置Mock状态,避免用例间污染 jest.resetAllMocks(); }); test('Mock返回的天气数据可正常渲染到页面', async () => { // 抽离固定Mock测试数据,方便断言复用 const mockWeather = { forcast: 'Sunny', max: 28, min: 17, description: 'Clear skys all day with a warm summber breaze ariving in the afternoon', }; // 固定axios.get的返回值 mockedAxios.get.mockResolvedValue({ data: { result: { weather: mockWeather, }, }, }); render(<Weather />); // findBy系列方法内置异步等待逻辑,等待组件渲染完成后校验字段 expect(await screen.findByText(mockWeather.description)).toBeInTheDocument(); expect(screen.getByText(mockWeather.forcast)).toBeInTheDocument(); expect(screen.getByText(`Temp: ${mockWeather.min} to ${mockWeather.max}`)).toBeInTheDocument(); }); });
关键说明
- 只需要Mock底层的axios请求方法即可,不需要导入或调用组件内部的请求函数,组件挂载后的副作用会自动触发Mock过的请求,拿到固定返回值后自动触发重渲染。
- 把Mock数据抽为常量后,断言直接引用常量值,避免硬编码字符串拼写错误导致测试误报,后续调整测试数据时也只需要修改一处。
- 异步场景优先使用
findBy*查询方法,比手动包裹waitFor的写法更简洁,也是React Testing Library官方推荐的最佳实践。 - 如果需要覆盖其他天气场景(比如下雪、多云),只需要修改Mock返回的
forcast字段,再等待对应文本/图标渲染即可,不需要改动测试的整体逻辑。
内容的提问来源于stack exchange,提问作者goatstash
相关产品推荐
相关产品推荐

