从Create React App升级到Vite后Jest测试遇语法错误
从Create React App迁移到Vite后Jest测试报错的解决方法
问题现象
将项目从Create React App升级到ViteJS后,运行Jest旧测试时抛出语法错误:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){.App { ^ SyntaxError: Unexpected token '.' 1 | import React from 'react'; > 2 | import './App.css'; | ^ 3 | import Home from "./Homepage/Home"; 4 | import { BrowserRouter, Routes, Route } from "react-router-dom"; 5 | import Tips from "./TipsPage/Tips"; at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1495:14) at Object.<anonymous> (src/App.tsx:2:1) at Object.<anonymous> (src/App.test.tsx:3:1)
已在package.json中配置ts-jest处理TypeScript文件,但问题依旧,相关配置片段:
"jest": { "verbose": true, "transform": { "^.+\\.tsx?$": "ts-jest" } },
问题根源
Jest默认无法解析CSS文件的导入语句,当测试中引入的组件包含CSS导入时,Jest会把CSS代码当作JavaScript解析,从而触发语法错误。
解决步骤
- 更新Jest配置
在package.json的jest字段中添加moduleNameMapper和testEnvironment配置:
"jest": { "verbose": true, "transform": { "^.+\\.tsx?$": "ts-jest" }, "moduleNameMapper": { "^.+\\.(css|sass|scss)$": "identity-obj-proxy" }, "testEnvironment": "jsdom" }
moduleNameMapper:指定用identity-obj-proxy模拟处理所有CSS/SASS/SCSS文件导入,避免Jest解析样式代码。testEnvironment:设置为jsdom,提供React组件测试所需的DOM环境(Jest 28+默认不再内置jsdom,若未安装需执行npm install --save-dev jest-environment-jsdom)。
- 确认依赖安装
确保identity-obj-proxy已在devDependencies中(你的package.json已包含),若缺失则执行:
npm install --save-dev identity-obj-proxy
- 检查测试文件导入
确保测试文件正确导入测试工具:
import { render, screen, fireEvent } from '@testing-library/react'; import App from './App';
- 重新运行测试
执行npm test,此时CSS导入会被正确处理,测试即可正常运行。
完整配置与测试代码
完整package.json
{ "name": "online-calculator", "version": "0.1.0", "private": true, "dependencies": { "@types/jest": "^29.5.2", "@types/node": "^20.2.5", "@types/react": "^18.2.8", "@types/react-dom": "^18.2.4", "bootstrap": "^5.3.0", "react": "^18.2.0", "react-bootstrap": "^2.7.4", "react-dom": "^18.2.0", "react-router-dom": "^6.11.2", "typescript": "^5.1.3", "web-vitals": "^3.3.2" }, "directories": {}, "scripts": { "start": "vite --port 3000", "build": "tsc && vite build", "serve": "vite preview", "test": "jest" }, "jest": { "verbose": true, "transform": { "^.+\\.tsx?$": "ts-jest" } }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@babel/preset-env": "^7.22.4", "@babel/preset-react": "^7.22.3", "@babel/preset-typescript": "^7.21.5", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "@vitejs/plugin-react": "^4.0.0", "eslint-config-react-app": "^7.0.1", "identity-obj-proxy": "^3.0.0", "jest": "^29.5.0", "ts-jest": "^29.1.0", "ts-node": "^10.9.1", "vite": "^4.3.9", "vite-plugin-svgr": "^3.2.0", "vite-tsconfig-paths": "^4.2.0" } }
测试代码
describe('Single Page Application Test', () => { it('should be a Single Page Application', () => { render( <App /> ); // Check if the Home component is rendered initially expect(screen.getByText("Offensive Manuevers")).toBeInTheDocument(); // Simulate navigating to the Tips page fireEvent.click(screen.getByText('Tips')); expect(screen.getByText('Tips Page Works')).toBeInTheDocument(); // Simulate navigating to the Contact page fireEvent.click(screen.getByText('Contact')); expect(screen.getByText('Contact Page Works')).toBeInTheDocument(); }); });
内容的提问来源于stack exchange,提问作者Tom Lin
相关产品推荐
相关产品推荐

