React Testing Library 中如何正确测试异步加载的数据?

一育柯 阅读 4

我用 React Testing Library 测试一个组件,它在 useEffect 里通过 fetch 获取数据并更新状态。但测试时总是拿不到渲染后的数据,断言失败。是不是要加 await 或者用 waitFor?

这是我的组件代码:

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch(<code>/api/users/${userId}</code>)
      .then(res => res.json())
      .then(data => setUser(data));
  }, [userId]);

  if (!user) return <div>Loading...</div>;
  return <div>{user.name}</div>;
}

测试里我 mock 了 fetch,但 screen.getByText 始终找不到 user.name,控制台显示还是 “Loading…”。该怎么写才对?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
萌新.艳丽
这种异步渲染的测试确实容易踩坑,我来给你个靠谱的解法。问题出在你的测试没有等数据加载完成就断言了。

首先确保你的测试文件顶部引入了这些:
import { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';


然后测试代码要这么写:
test('should display user name after loading', async () => {
// mock服务端返回
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ name: '老王' }),
})
);

render();

// 先验证loading状态
expect(screen.getByText('Loading...')).toBeInTheDocument();

// 关键在这里:等异步渲染完成
await waitFor(() => {
expect(screen.getByText('老王')).toBeInTheDocument();
});
});


几个关键点:
1. 测试函数要用async声明
2. 用waitFor包裹最终的断言,它会自动重试直到超时
3. 别忘了await waitFor

我经常遇到这种问题,特别是刚用RTL的时候。有时候还会配合findByText使用,但waitFor更通用些。如果还不行,可能是你的mock没设置对,检查下fetch的mock实现。
点赞
2026-03-05 13:03