如何修复 NextJS14 和 Jest 的环境变量无效错误?

问题描述 投票:0回答:1

我正在使用 @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)
}

next.js jestjs
1个回答
-1
投票

添加dotenv来修复

import { createEnv } from '@t3-oss/env-nextjs'
import { config } from 'dotenv'
import { z } from 'zod'

config()

export const env = createEnv({})
© www.soinside.com 2019 - 2024. All rights reserved.