如何在服务端mock Next.js客户端动态导入以适配Jest SSR测试
适配Next.js SSR Jest测试的动态导入Mock方案
核心思路
通过手动Mock next/dynamic 模块,根据导入配置的ssr参数做分支处理,同时改造预加载逻辑过滤客户端动态导入,既保留node测试环境的浏览器API校验能力,又符合两类动态导入的快照预期。
实现步骤
1. 创建next/dynamic手动Mock
在项目根目录的__mocks__/next/dynamic.js文件中添加如下代码:
const actualDynamic = jest.requireActual('next/dynamic').default; // 存储所有服务端动态导入的加载器 const ssrImportLoaders = []; const mockDynamic = (loader, options = {}) => { // 客户端动态导入(ssr显式为false):直接返回空组件,SSR渲染时不输出内容 if (options.ssr === false) { return () => null; } // 服务端动态导入:加入预加载队列,走原生dynamic逻辑 ssrImportLoaders.push(loader); return actualDynamic(loader, options); }; // 自定义预加载方法,仅预加载服务端动态导入 export const preloadSsrDynamic = async () => { await Promise.all(ssrImportLoaders.map(loader => loader())); // 清空队列避免跨用例污染 ssrImportLoaders.length = 0; }; export default mockDynamic;
2. 配置Jest识别Mock
在jest.config.js中确认如下配置:
module.exports = { testEnvironment: 'node', // 确保手动Mock生效 resetMocks: false, // 可选:如果需要全局生效,可在setupFilesAfterEnv中引入Mock setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], };
可以直接卸载jest-next-dynamic依赖,上述方案已经内置了服务端动态导入的预加载能力,避免原库处理ssr:false导入时的报错问题。
3. 调整SSR测试用例
在SSR测试的前置钩子中调用自定义预加载方法即可:
import { preloadSsrDynamic } from '__mocks__/next/dynamic'; import { renderToString } from 'react-dom/server'; import App from '../pages/index'; beforeAll(async () => { // 仅预加载服务端动态导入 await preloadSsrDynamic(); }); test('SSR 渲染快照符合预期', () => { const html = renderToString(<App />); expect(html).toMatchSnapshot(); });
效果验证
- 服务端动态导入的组件会正常预加载并渲染,完整出现在SSR快照中
- 客户端动态导入的组件返回空函数,SSR快照中不会出现对应内容
- 测试环境保持node,服务端代码如果误引用
window等浏览器API会直接抛出错误,符合SSR测试的校验要求
注:此前误以为Jest不支持按入参条件Mock,实际是Mock返回函数即可接收动态导入的配置参数,自由实现分支逻辑。
内容的提问来源于stack exchange,提问作者tunesmith
相关产品推荐
相关产品推荐

