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

Next.js+Jest环境中无法Mock JSX/TSX组件的问题排查

解决Jest Mock Next.js组件时的转译错误

问题场景

在使用Next.js、Jest和React Testing Library进行测试时,尝试Mock ui/forms/Field/Field组件,使用以下代码:

jest.mock('ui/forms/Field/Field', () => {
    const original = jest.requireActual('ui/forms/Field/Field');
    return {
        __esModule: true,
        ...original,
        Field: (props: any) => <div ref={props.inputRef}></div>,
    };
});

执行测试时出现错误:

Property declarations[0] of VariableDeclaration expected node to be of a type ["VariableDeclarator"] but instead got undefined

当前jest.config.js配置如下:

module.exports = {
    collectCoverage: true,
    coverageProvider: 'v8',
    collectCoverageFrom: ['<rootDir>/src/templates/ui/forms/**/*{.tsx,.jsx}'],
    moduleNameMapper: {
        '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
        '^.+\\.(css|sass|scss)$': '<rootDir>/jest/mocks/style.js',
        '^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$/i': `<rootDir>/jest/mocks/file.js`,
        '^templates/(.*)$': '<rootDir>/src/templates/$1',
        '^scripts/(.*)$': '<rootDir>/src/scripts/$1',
        '^ui/(.*)$': '<rootDir>/src/templates/ui/$1',
    },
    testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
    testEnvironment: 'jsdom',
    transform: {
        '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
    },
    transformIgnorePatterns: ['/node_modules/', '^.+\\.module\\.(css|sass|scss)$'],
};

解决方案

这个错误的核心原因是Jest会将jest.mock的工厂函数提升到模块顶部执行,而此时JSX/TSX语法还未经过Babel转译,Node.js无法识别JSX语法,导致转译报错。可以通过以下两种方式解决:

方案1:用React.createElement替代JSX语法

在jest.mock的工厂函数中,避免直接写JSX,改用React.createElement构造元素:

jest.mock('ui/forms/Field/Field', () => {
    const React = require('react');
    const original = jest.requireActual('ui/forms/Field/Field');
    return {
        __esModule: true,
        ...original,
        Field: (props: any) => React.createElement('div', { ref: props.inputRef }),
    };
});

方案2:使用单独的__mocks__文件

将Mock组件抽离到单独的文件中,让Jest自动加载该Mock,这样文件会正常经过Babel转译:

  1. 在项目中创建路径:__mocks__/ui/forms/Field/Field.tsx
  2. 在该文件中编写Mock组件:
import React from 'react';
import * as originalModule from 'ui/forms/Field/Field';

export const Field = (props: any) => <div ref={props.inputRef}></div>;

// 导出原模块的其他内容
export default { ...originalModule, Field };
  1. 在测试文件中只需调用jest.mock('ui/forms/Field/Field')即可,无需工厂函数:
jest.mock('ui/forms/Field/Field');

额外检查

如果以上方案仍未解决,可确认以下配置:

  • 确保next/babel预设已正确安装(通常Next.js项目默认包含)
  • 检查transform配置是否覆盖了所有TSX/JSX文件,当前配置中的'^.+\\.(js|jsx|ts|tsx)$'规则是正确的
  • 确认testEnvironment设置为jsdom(已在配置中设置)

内容的提问来源于stack exchange,提问作者Сапижат Гаджи</think_never_used_51bce0c785ca2f68081bfa7d91973934>

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:32:54