Skip to main content

使用 Next.js 设置 Jest

Jest 和 React 测试库经常一起用于单元测试和快照测试。本指南将向你展示如何使用 Next.js 设置 Jest 并编写你的第一个测试。

¥Jest and React Testing Library are frequently used together for Unit Testing and Snapshot Testing. This guide will show you how to set up Jest with Next.js and write your first tests.

很高兴知道:由于 async 服务器组件对于 React 生态系统来说是新的,因此 Jest 目前不支持它们。虽然你仍然可以对同步服务器和客户端组件运行单元测试,但我们建议对 async 组件使用 E2E 测试。

¥Good to know: Since async Server Components are new to the React ecosystem, Jest currently does not support them. While you can still run unit tests for synchronous Server and Client Components, we recommend using an E2E tests for async components.

快速开始

¥Quickstart

你可以将 create-next-app 与 Next.js with-jest 示例结合使用来快速入门:

¥You can use create-next-app with the Next.js with-jest example to quickly get started:

npx create-next-app@latest --example with-jest with-jest-app

手动设置

¥Manual setup

Next.js 12 发布以来,Next.js 现在具有 Jest 的内置配置。

¥Since the release of Next.js 12, Next.js now has built-in configuration for Jest.

要设置 Jest,请安装 jest 和以下软件包作为开发依赖:

¥To set up Jest, install jest and the following packages as dev dependencies:

npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom
# or
yarn add -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom
# or
pnpm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom

通过运行以下命令生成基本的 Jest 配置文件:

¥Generate a basic Jest configuration file by running the following command:

npm init jest@latest
# or
yarn create jest@latest
# or
pnpm create jest@latest

这将引导你完成一系列提示,为你的项目设置 Jest,包括自动创建 jest.config.ts|js 文件。

¥This will take you through a series of prompts to setup Jest for your project, including automatically creating a jest.config.ts|js file.

更新你的配置文件以使用 next/jest。该转换器具有 Jest 与 Next.js 配合使用所需的所有配置选项:

¥Update your config file to use next/jest. This transformer has all the necessary configuration options for Jest to work with Next.js:

import type { Config } from 'jest'
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
const config: Config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)
const nextJest = require('next/jest')

/** @type {import('jest').Config} */
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
const config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(config)

在后台,next/jest 会自动为你配置 Jest,包括:

¥Under the hood, next/jest is automatically configuring Jest for you, including:

  • 使用 Next.js 编译器 设置 transform

    ¥Setting up transform using the Next.js Compiler

  • 自动模拟样式表(.css.module.css 及其 scss 变体)、图片导入和 next/font

    ¥Auto mocking stylesheets (.css, .module.css, and their scss variants), image imports and next/font

  • .env(和所有变体)加载到 process.env

    ¥Loading .env (and all variants) into process.env

  • 从测试解析和转换中忽略 node_modules

    ¥Ignoring node_modules from test resolving and transforms

  • 从测试解析中忽略 .next

    ¥Ignoring .next from test resolving

  • 加载 next.config.js 以获取启用 SWC 转换的标志

    ¥Loading next.config.js for flags that enable SWC transforms

很高兴知道:要直接测试环境变量,请在单独的安装脚本或 jest.config.ts 文件中手动加载它们。欲了解更多信息,请参阅 测试环境变量

¥Good to know: To test environment variables directly, load them manually in a separate setup script or in your jest.config.ts file. For more information, please see Test Environment Variables.

可选的:处理绝对导入和模块路径别名

¥Optional: Handling Absolute Imports and Module Path Aliases

如果你的项目使用 模块路径别名,则需要配置 Jest 以通过将 jsconfig.json 文件中的 paths 选项与 jest.config.js 文件中的 moduleNameMapper 选项匹配来解析导入。例如:

¥If your project is using Module Path Aliases, you will need to configure Jest to resolve the imports by matching the paths option in the jsconfig.json file with the moduleNameMapper option in the jest.config.js file. For example:

{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler",
"baseUrl": "./",
"paths": {
"@/components/*": ["components/*"]
}
}
}
moduleNameMapper: {
// ...
'^@/components/(.*)$': '<rootDir>/components/$1',
}

可选的:使用自定义匹配器扩展 Jest

¥Optional: Extend Jest with custom matchers

@testing-library/jest-dom 包括一组方便的 自定义匹配器(例如 .toBeInTheDocument()),使编写测试变得更容易。你可以通过将以下选项添加到 Jest 配置文件来为每个测试导入自定义匹配器:

¥@testing-library/jest-dom includes a set of convenient custom matchers such as .toBeInTheDocument() making it easier to write tests. You can import the custom matchers for every test by adding the following option to the Jest configuration file:

setupFilesAfterEnv: ['<rootDir>/jest.setup.ts']
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']

然后,在 jest.setup.ts 内添加以下导入:

¥Then, inside jest.setup.ts, add the following import:

import '@testing-library/jest-dom'
import '@testing-library/jest-dom'

很高兴知道:extend-expectv6.0 被删除,因此如果你在版本 6 之前使用 @testing-library/jest-dom,则需要导入 @testing-library/jest-dom/extend-expect

¥Good to know:extend-expect was removed in v6.0, so if you are using @testing-library/jest-dom before version 6, you will need to import @testing-library/jest-dom/extend-expect instead.

如果你需要在每次测试前添加更多设置选项,可以将它们添加到上面的 jest.setup.js 文件中。

¥If you need to add more setup options before each test, you can add them to the jest.setup.js file above.

添加测试脚本到 package.json

¥Add a test script to package.json:

最后,将 Jest test 脚本添加到 package.json 文件中:

¥Finally, add a Jest test script to your package.json file:

{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"test": "jest",
"test:watch": "jest --watch"
}
}

当文件更改时,jest --watch 将重新运行测试。有关更多 Jest CLI 选项,请参阅 Jest 文档

¥jest --watch will re-run tests when a file is changed. For more Jest CLI options, please refer to the Jest Docs.

创建你的第一个测试:

¥Creating your first test:

你的项目现在已准备好运行测试。在项目的根目录中创建一个名为 __tests__ 的文件夹。

¥Your project is now ready to run tests. Create a folder called __tests__ in your project's root directory.

例如,我们可以添加一个测试来检查 <Page /> 组件是否成功渲染标题:

¥For example, we can add a test to check if the <Page /> component successfully renders a heading:

import Link from 'next/link'

export default function Home() {
return (
<div>
<h1>Home</h1>
<Link href="/about">About</Link>
</div>
)
}
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import Page from '../app/page'

describe('Page', () => {
it('renders a heading', () => {
render(<Page />)

const heading = screen.getByRole('heading', { level: 1 })

expect(heading).toBeInTheDocument()
})
})

(可选)添加 快照测试 来跟踪组件中的任何意外更改:

¥Optionally, add a snapshot test to keep track of any unexpected changes in your component:

import { render } from '@testing-library/react'
import Page from '../app/page'

it('renders homepage unchanged', () => {
const { container } = render(<Page />)
expect(container).toMatchSnapshot()
})

运行你的测试

¥Running your tests

然后,运行以下命令来运行测试:

¥Then, run the following command to run your tests:

npm run test
# or
yarn test
# or
pnpm test

其他资源

¥Additional Resources

为了进一步阅读,你可能会发现这些资源很有帮助:

¥For further reading, you may find these resources helpful: