Next.js中使用Jest测试时Firestore导入报错问题
解决Next.js+Jest测试Firebase时的"Cannot use import statement outside a module"错误
问题重现
在Next.js项目中使用Jest运行导入Firebase的组件测试时,抛出以下错误:
import { registerVersion } from '@firebase/app'; SyntaxError: Cannot use import statement outside a module
其他模块导入测试正常,仅Firebase相关代码触发该错误,更换测试环境后仍存在问题。
项目相关配置文件如下:
package.json
{ "name": "chat", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "test": "jest --forceExit --watchAll --coverage" }, "dependencies": { "@firebase/testing": "^0.20.11", "firebase": "^9.9.4", "kill-port": "^2.0.1", "next": "12.2.5", "react": "18.2.0", "react-dom": "18.2.0", "react-firebase-hooks": "^5.0.3", "react-hot-toast": "^2.3.0", "uuid": "^8.3.2" }, "devDependencies": { "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/preset-react": "^7.18.6", "@firebase/rules-unit-testing": "^2.0.4", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@types/jest": "^29.0.2", "eslint": "8.23.0", "eslint-config-next": "12.2.5", "firebase-admin": "^11.0.1", "jest": "^29.0.3", "jest-environment-jsdom": "^29.0.3" } }
jest.config.js
// jest.config.js const nextJest = require('next/jest'); const createJestConfig = nextJest({ // Provide the path to your Next.js app to load next.config.js and .env files in your test environment dir: './', }); // Add any custom config to be passed to Jest /** @type {import('jest').Config} */ const customJestConfig = { // Add more setup options before each test is run // setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work //moduleDirectories: ['node_modules', '<rootDir>/'], testEnvironment: 'jest-environment-jsdom', }; // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async module.exports = createJestConfig(customJestConfig);
test/page.test.js
/** * @jest-environment jest-environment-jsdom */ import React from 'react'; import { render, screen } from '@testing-library/react'; import Thing from '../../pages/thing.jsx'; describe('testing Home page', () => { test('render h1 element', () => { expect(render(<Thing />)); }); });
pages/thing.jsx
import { firestore } from "../lib/firebase"; export default function Thing({ }) { return ( <main> </main> ); }
lib/firebase.js(已移除敏感配置)
import { initializeApp } from 'firebase/app'; import { getAuth, GoogleAuthProvider } from 'firebase/auth'; import { getFirestore } from 'firebase/firestore'; import { getStorage } from 'firebase/storage'; const firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", measurementId: "" }; const app = initializeApp(firebaseConfig); export const auth = getAuth(app); export const googleAuthProvider = new GoogleAuthProvider(); export const firestore = getFirestore(app); export const storage = getStorage(app);
解决方案
1. 修改Jest配置,添加转译忽略规则
Firebase v9+采用ES模块格式,Jest默认不会转译node_modules中的ES模块,导致报错。需要在jest.config.js的customJestConfig中添加transformIgnorePatterns,指定不忽略Firebase相关模块:
const customJestConfig = { testEnvironment: 'jest-environment-jsdom', // 添加以下配置 transformIgnorePatterns: [ '/node_modules/(?!firebase|@firebase|firebase-admin)/', ], };
2. 确保Babel配置兼容(可选)
如果项目根目录没有.babelrc或babel.config.js,可以创建一个babel.config.js文件,确保Next.js和Jest的Babel配置统一:
module.exports = { presets: ['next/babel'], };
3. 优化测试文件的环境声明
可以移除测试文件顶部的@jest-environment注释,因为已经在jest.config.js中全局指定了testEnvironment: 'jest-environment-jsdom',避免重复配置。
4. 调整测试命令(可选)
如果上述配置仍有问题,可以尝试在package.json的test命令中添加--experimental-vm-modules参数(适用于Node.js 16+):
"scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest --forceExit --watchAll --coverage" }
验证修改
完成配置调整后,重新运行测试命令:
npm run test
此时Firebase相关的导入应该可以正常被Jest处理,不再抛出语法错误。
内容的提问来源于stack exchange,提问作者Seesi L
相关产品推荐
相关产品推荐

