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

Next.js 14页面路由应用Jest测试:getStaticProps环境变量不生效问题

问题

我有一个基于Next 14 page router的简单应用,想通过直接给页面传props的方式用Jest做UI测试,同时不想触发getStaticProps函数。我尝试在测试环境里用process.env.NODE_ENV让getStaticProps直接返回,但执行npm test时发现,getStaticProps里的process.env.NODE_ENV始终不是test,导致数据库相关的代码报错;但只要注释掉getStaticProps里的所有代码,测试就能正常通过。

首页代码(index.tsx):

const Home = (props: dataType) => {
    const data = props.posts;
    if(data.length === 0) return <p style={{textAlign:"center"}}> Loading ...</p>
    return (
        <div className={classes.home}>
             <h1 className={classes["home--header"]}>Blog Post App</h1>
             <h3 className={classes["home--header"]}>showing blog posts</h3>
            <div className={classes['home--main']}>
           {data.map(post=>{
            return <BlogCard key={post["_id"].toString()} 
               id={post["_id"].toString()} title={post.title} text={post.text}  />
         })}
  
      </div>
 </div>
);
};

export async function getStaticProps(){
 console.log(process.env.NODE_ENV);
 if(process.env.NODE_ENV=== "test") return;
   const client = await clientPromise;
   const db = client.db("blogpost");
   const postCollection = db.collection("posts");

   const allPosts = await postCollection.find({}).toArray();

  return {
      props:{posts:JSON.parse(JSON.stringify(allPosts))},
      revalidate:60*5

      };

   }

测试代码(home.test.tsx):

import { render, screen } from "@testing-library/react";
import '@testing-library/jest-dom'
import Home from "@/pages/index";

describe("Home",(()=>{

    test("testing page uses correct Env",()=>{
    const test_env = process.env.NODE_ENV;

    expect(test_env).toBe("test");

     // 这个测试能通过

     });

test("home page has correct heading", () => {
   render(
     <Home
       posts={[
          { _id: "1", title: "test post", text: "this is a test for Home page" },
         ]}
     />
   );

     const heading = screen.getByRole("heading",{name:/blog post app/i});

     expect(heading).toBeInTheDocument();


     const postTitle = screen.getByTestId("postTitle");
  
    expect(postTitle).toBeInTheDocument();
 });

}));
解决方案

1. 显式设置测试环境变量

Jest默认会把NODE_ENV设为test,但Next.js处理页面组件时可能存在环境变量隔离。可以在Jest配置文件中显式注入:

  • 在jest.config.js中确保测试环境为jsdom:
module.exports = {
  testEnvironment: 'jsdom',
  setupFiles: ['./jest.setup.js'],
  // 其他配置项
};
  • 在jest.setup.js中强制设置环境变量:
process.env.NODE_ENV = 'test';

2. Mock getStaticProps函数

测试时直接Mock掉getStaticProps,不让它执行数据库逻辑:

import { render, screen } from "@testing-library/react";
import '@testing-library/jest-dom';
import Home from "@/pages/index";

// Mock getStaticProps,阻止其执行原逻辑
jest.mock('@/pages/index', () => {
  const original = jest.requireActual('@/pages/index');
  return {
    ...original,
    getStaticProps: jest.fn().mockResolvedValue({ props: { posts: [] } }),
  };
});

describe("Home", () => {
  test("testing page uses correct Env", () => {
    expect(process.env.NODE_ENV).toBe("test");
  });

  test("home page has correct heading", () => {
    render(
      <Home
        posts={[
          { _id: "1", title: "test post", text: "this is a test for Home page" },
        ]}
      />
    );

    const heading = screen.getByRole("heading", { name: /blog post app/i });
    expect(heading).toBeInTheDocument();

    const postTitle = screen.getByTestId("postTitle");
    expect(postTitle).toBeInTheDocument();
  });
});

3. 分离UI组件与数据逻辑

把页面的UI部分抽成独立组件,彻底和getStaticProps解耦,测试时直接针对UI组件:

  • 新建components/HomeUI.tsx:
const HomeUI = (props: dataType) => {
  const data = props.posts;
  if(data.length === 0) return <p style={{textAlign:"center"}}> Loading ...</p>
  return (
    <div className={classes.home}>
         <h1 className={classes["home--header"]}>Blog Post App</h1>
         <h3 className={classes["home--header"]}>showing blog posts</h3>
        <div className={classes['home--main']}>
       {data.map(post=>{
        return <BlogCard key={post["_id"].toString()} 
           id={post["_id"].toString()} title={post.title} text={post.text}  />
     })}

  </div>
</div>
);
};

export default HomeUI;
  • 修改pages/index.tsx:
import HomeUI from '@/components/HomeUI';

export default function Home(props: dataType) {
  return <HomeUI {...props} />;
}

export async function getStaticProps(){
 console.log(process.env.NODE_ENV);
 if(process.env.NODE_ENV=== "test") return;
   const client = await clientPromise;
   const db = client.db("blogpost");
   const postCollection = db.collection("posts");

   const allPosts = await postCollection.find({}).toArray();

  return {
      props:{posts:JSON.parse(JSON.stringify(allPosts))},
      revalidate:60*5
      };
}
  • 测试文件修改为测试HomeUI:
import { render, screen } from "@testing-library/react";
import '@testing-library/jest-dom';
import HomeUI from "@/components/HomeUI";

describe("HomeUI", () => {
  test("home page has correct heading", () => {
    render(
      <HomeUI
        posts={[
          { _id: "1", title: "test post", text: "this is a test for Home page" },
        ]}
      />
    );

    const heading = screen.getByRole("heading", { name: /blog post app/i });
    expect(heading).toBeInTheDocument();

    const postTitle = screen.getByTestId("postTitle");
    expect(postTitle).toBeInTheDocument();
  });
});

4. 检查Next.js测试配置

确保项目使用@testing-library/jest-dom和jsdom测试环境,避免服务器端环境变量干扰,同时确保next/jest配置正确(如果使用官方测试工具链)。

内容的提问来源于stack exchange,提问作者AmirHossein_Khakshouri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 18:04:52