我正在使用 @t3-oss/env-nextjs 来管理 NextJS 项目中的环境变量,但是,当我尝试运行 Jest 时,出现以下错误:
FAIL tests/hello.spec.tsx
● Test suite failed to run
Invalid environment variables
2 | import { z } from 'zod'
3 |
> 4 | export const env = createEnv({
| ^
5 | server: {
6 | APP_URL: z.string().url(),
7 | },
看起来第 4 行是问题所在,但为什么呢?这个 Env 工作正常,这个错误仅在我运行 Jest 时发生,这是我的 env.ts:
import { createEnv } from '@t3-oss/env-nextjs'
import { z } from 'zod'
export const env = createEnv({
server: {
APP_URL: z.string().url(),
},
client: {
NEXT_PUBLIC_API_BASE_URL: z.string().url(),
},
runtimeEnv: {
APP_URL: process.env.APP_URL,
NEXT_PUBLIC_API_BASE_URL: process.env.NEXT_PUBLIC_API_BASE_URL,
},
})
这是我的 jest.setup.js:
import '@testing-library/jest-dom'
import { loadEnvConfig } from '@next/env'
loadEnvConfig(process.cwd())
这是我的 jest.config.mjs:
import nextJest from 'next/jest.js'
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 config = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
setupFiles: ['<rootDir>/.env.test'],
setupFilesAfterEnv: ['./jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)
这是我的 next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
images: {
domains: ['github.com'],
},
}
module.exports = nextConfig
这是package.json,我没有使用Babel,我选择了SWC:
{
"name": "devstoreplus",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"cypress:open": "cypress open",
"test": "jest --watch"
},
"dependencies": {
"@t3-oss/env-nextjs": "^0.7.1",
"lucide-react": "^0.292.0",
"next": "14.0.1",
"react": "^18",
"react-dom": "^18",
"tailwind-merge": "^2.0.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@rocketseat/eslint-config": "^2.1.0",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^14.1.2",
"@testing-library/user-event": "^14.5.1",
"@types/jest": "^29.5.8",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@typescript-eslint/parser": "^5.62.0",
"autoprefixer": "^10.0.1",
"cypress": "^13.5.1",
"eslint": "^8.7.0",
"eslint-config-next": "14.0.1",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8",
"prettier": "^2.5.1",
"tailwindcss": "^3.3.0",
"typescript": "^5.2.2"
}
}
最后这是我尝试运行的测试代码,但只是渲染页面主页的测试:
import { render, screen } from '@testing-library/react'
import Home from '../src/app/(store)/(home)/page'
import React from 'react'
describe('Home component', () => {
test('renders highlighted product', async () => {
const { getByText } = render(<Home />)
expect(getByText('Moletom')).toBeTruthy()
})
})
在主页中有一个对假 API 的调用:
export default async function Home() {
const products = await getFeaturedProducts()
console.log(products)
const [highlightedProduct, ...otherProducts] = await getFeaturedProducts()
我的 .env.local 位于根文件夹中:
NEXT_PUBLIC_API_BASE_URL = "https://api-devstore.vercel.app"
APP_URL = "http://localhost:3000"
API:
import { env } from '@/env'
export function api(path: string, init?: RequestInit) {
const baseUrl = env.NEXT_PUBLIC_API_BASE_URL
const apiPrefix = '/api'
const url = new URL(apiPrefix.concat(path), baseUrl)
return fetch(url, init)
}
添加dotenv来修复
import { createEnv } from '@t3-oss/env-nextjs'
import { config } from 'dotenv'
import { z } from 'zod'
config()
export const env = createEnv({})