React测试:如何验证useEffect从API取值后的TVL大于0?
解决React Testing Library验证TVL值的问题
问题根源
测试失败是因为组件初始化时totalCostakedBtc和btcPrice都是0,而API请求是异步操作,GPT生成的代码没有等待异步请求完成就直接断言,拿到的是初始渲染的0值,自然无法通过“大于0”的校验。
解决方案步骤
- 模拟API请求:在测试中模拟API返回有效数据,避免依赖真实接口,同时确保状态能正确更新。
- 等待异步更新:使用React Testing Library提供的异步查询方法,等待状态更新后再获取目标元素。
- 解析格式化数值:由于TVL是经过
formatNumber格式化后的字符串,需要先解析成数值再断言。
示例代码
组件代码(参考)
import { useState, useEffect } from 'react'; import { formatNumber } from './utils'; // 假设格式化函数存放在此处 const TVLComponent = () => { const [totalStakedBtc, setTotalStakedBtc] = useState(0); const [btcPrice, setBtcPrice] = useState(0); useEffect(() => { const fetchData = async () => { // 实际API请求逻辑 const res = await fetch('/api/tvl-data'); const data = await res.json(); setTotalStakedBtc(data.totalStakedBtc); setBtcPrice(data.btcPrice); }; fetchData(); }, []); const tvl = totalStakedBtc * btcPrice; return ( <div data-testid="loaded-TVL"> {formatNumber(tvl)} </div> ); }; export default TVLComponent;
测试代码(Jest + React Testing Library + MSW模拟API)
import { render, screen } from '@testing-library/react'; import TVLComponent from './TVLComponent'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; // 模拟API服务器,拦截请求并返回预设数据 const server = setupServer( rest.get('/api/tvl-data', (req, res, ctx) => { return res(ctx.json({ totalStakedBtc: 100, btcPrice: 30000 // 乘积为3,000,000,满足大于0的条件 })); }) ); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); test('TVL值大于0', async () => { render(<TVLComponent />); // 异步等待元素更新,获取格式化后的TVL文本 const tvlElement = await screen.findByTestId('loaded-TVL'); // 处理格式化字符串(比如去除千分位逗号),转换为数值 const tvlValue = parseFloat(tvlElement.textContent.replace(/,/g, '')); // 断言数值大于0 expect(tvlValue).toBeGreaterThan(0); });
关键说明
- 模拟API:用MSW拦截真实API请求,返回预设的有效数据,确保组件状态能更新为非0值。
- 异步查询:
findByTestId是异步查询方法,会自动等待组件状态更新、元素内容变化后返回结果,替代同步的getByTestId,避免拿到初始的0值。 - 数值解析:格式化后的字符串可能包含千分位逗号或其他符号,需要先处理成纯数值再进行断言。
如果不想使用MSW,也可以用jest.mock直接模拟API请求函数,核心思路都是确保异步请求完成后再执行断言逻辑。
内容的提问来源于stack exchange,提问作者Prabhat kumar
相关产品推荐
相关产品推荐

