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

如何在Jest中加载Next.js配置并启用Server Actions特性标志

解决Jest测试Server Action时提示需启用特性标志的问题

核心问题分析

你当前的next/config模拟层级错误,Next.js的serverActions配置属于根级的experimental对象,而非publicRuntimeConfig内部;另外jest配置里的setup文件后缀不匹配,可能导致模拟代码未生效。

修复步骤

1. 修正next/config的模拟结构

修改jest.setup.ts,将serverActions放在正确的配置层级:

jest.mock('next/config', () => () => ({
  experimental: {
    typedRoutes: true,
    serverActions: true,
  },
  publicRuntimeConfig: {}, // 保留原有public配置(如有需要)
}));

2. 对齐jest配置的setup文件后缀

你的jest.config.js指定的是jest.setup.js,但实际文件为jest.setup.ts,需统一后缀:

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'], // 改为ts后缀
  // ...其他配置保持不变
};

3. 更可靠的方案:直接Mock Server Action

测试组件逻辑时,无需纠结Next.js配置,直接mock组件内调用的apiCall函数更高效:

  • 调整Form组件,将apiCall作为props传入:
const Form = ({ mockSubmit, apiCall }: { mockSubmit: () => void; apiCall: (data: any) => Promise<void> }) => {
 const handleSubmit = async (data) => {
  await apiCall(data);
  mockSubmit();
 };

 return (
  <form onSubmit={handleSubmit}>
   <input name="name" />
   <button type="submit">Submit</button>
  </form>
 );
};
  • 测试代码中mockapiCall:
describe('Create form', () => {
  it('should trigger submit after typing', async () => {
    const mockSubmit = jest.fn();
    const mockApiCall = jest.fn(); // Mock Server Action
    const { user } = userEventsTestSetup(
      <Form mockSubmit={mockSubmit} apiCall={mockApiCall}/>
    );
    await user.type(screen.getByRole('textbox', { name: 'name' }), 'ABCD');
    await user.click(screen.getByRole('button', { name: 'Submit' }));
    expect(mockApiCall).toHaveBeenCalledWith(expect.objectContaining({ name: 'ABCD' }));
    expect(mockSubmit).toHaveBeenCalled();
  });
});

额外注意事项

  • 确保你的Next.js版本为v13.4+(Server Action的最低支持版本)
  • 如果Server Action使用了use server指令,可直接用jest.mock mock对应的模块

内容的提问来源于stack exchange,提问作者Re-Angelo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:47:25