You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS App Router异步组件测试报错:fetch未定义及渲染问题

解决Next.js App Router异步页面测试的两个问题

1. 修复ReferenceError: fetch is not defined

Jest运行在Node.js环境中,Node.js v18之前默认没有内置fetchAPI,解决方式分两种:

方式一:用Next.js官方Jest预设

Next.js的next/jest预设已经内置了fetch的polyfill,确保你的Jest配置正确:
在项目根目录的jest.config.js中添加:

const nextJest = require('next/jest')

const createJestConfig = nextJest({
  dir: './', // 你的Next.js项目根目录
})

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment: 'jest-environment-jsdom',
}

module.exports = createJestConfig(customJestConfig)

方式二:手动添加polyfill

如果不想依赖官方预设,可自行安装并导入:

  • 安装依赖:npm install whatwg-fetch --save-dev
  • 在jest.setup.js中导入:import 'whatwg-fetch';

2. 正确测试异步页面组件

App Router的页面组件是异步函数(返回Promise),直接render(<UsersPage />)会报错,因为React无法渲染Promise对象。需要用Suspense组件包裹,并通过异步查询等待数据加载完成。

测试示例(mock fetch)

假设你的app/users/page.js代码如下:

async function getUsers() {
  const res = await fetch('https://api.example.com/users');
  return res.json();
}

export default async function UsersPage() {
  const users = await getUsers();
  return (
    <div>
      <h1>Users</h1>
      <ul>{users.map(user => <li key={user.id}>{user.name}</li>)}</ul>
    </div>
  );
}

对应的测试代码:

import { render, screen, waitFor } from '@testing-library/react';
import UsersPage from '../app/users/page';
import { Suspense } from 'react';

// Mock全局fetch
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve([{ id: 1, name: 'Test User' }]),
  })
);

describe('/users 页面测试', () => {
  // 测试后清除mock
  afterEach(() => jest.clearAllMocks());

  it('获取并渲染用户列表', async () => {
    // 用Suspense包裹异步页面,添加加载占位
    render(
      <Suspense fallback={<div>加载中...</div>}>
        <UsersPage />
      </Suspense>
    );

    // 验证fetch是否被正确调用
    await waitFor(() => {
      expect(fetch).toHaveBeenCalledWith('https://api.example.com/users');
    });

    // 等待用户列表渲染完成并验证
    const userItem = await screen.findByText('Test User');
    expect(userItem).toBeInTheDocument();
  });
});

关键要点

  • 必须用Suspense包裹异步页面组件,模拟Next.js渲染Server Component的行为
  • 使用screen.findBy*(异步查询)或waitFor等待数据加载完成,避免过早断言
  • 直接mock全局fetch即可,无需单独mock页面内部的getUsers函数,更贴近真实场景

内容的提问来源于stack exchange,提问作者medev21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:32:45