求助:Next 13中如何用Jest测试异步Server Component
Next.js 13+ 异步Server Component的Jest测试方案
直接用React Testing Library渲染异步Server Component会触发Objects are not valid as a React child (found: [object Promise])错误,本质原因是异步组件返回的是Promise而非React元素,React测试工具默认不支持直接渲染异步根组件。以下是可行的解决方法:
方法一:手动解析异步组件Promise
直接调用异步组件函数,等待其返回JSX后再传入render方法:
it('should render without crashing', async () => { // 提前mock好getArtist、getArtistAlbums等异步依赖 jest.mock('../utils/api', () => ({ getArtist: () => Promise.resolve({ name: 'Bob Dylan' }), getArtistAlbums: () => Promise.resolve([]) })); // 手动调用异步组件,获取JSX const jsx = await Page({ params: { username: 'Bob Dylan' } }); // 渲染拿到的JSX const { container } = render(jsx); // 执行断言 expect(container.querySelector('h1')).toHaveTextContent('Bob Dylan'); });
方法二:封装异步渲染工具函数
重复手动解析Promise太繁琐,可以封装一个通用工具函数:
// 测试工具文件中定义 async function renderAsync(Component, props = {}) { const jsx = await Component(props); return render(jsx); } // 测试用例中使用 it('should render artist and their albums', async () => { // 配置mock jest.mock('../utils/api', () => ({ getArtist: () => Promise.resolve({ name: 'Bob Dylan' }), getArtistAlbums: () => Promise.resolve([ { title: 'Highway 61 Revisited' }, { title: 'Blonde on Blonde' } ]) })); // 使用封装的工具渲染异步组件 const { container } = await renderAsync(Page, { params: { username: 'Bob Dylan' } }); // 验证渲染结果 expect(container.querySelector('h1')).toHaveTextContent('Bob Dylan'); expect(container.querySelectorAll('.album-title')).toHaveLength(2); });
注意事项
- 必须确保所有异步依赖(如数据请求函数)都被正确mock,避免触发真实网络请求
- 如果组件内部嵌套了其他异步Server Component,同样需要在测试时手动解析或mock其依赖,因为测试环境不会像Next.js服务端那样自动处理异步组件的嵌套解析
内容的提问来源于stack exchange,提问作者Felipe
相关产品推荐
相关产品推荐

