Menu

Jest mit Next.js einrichten

Jest und React Testing Library werden häufig zusammen für Unit-Tests und Snapshot-Tests verwendet. Diese Anleitung zeigt Ihnen, wie Sie Jest mit Next.js einrichten und Ihre ersten Tests schreiben.

Hinweis: Da async Server-Komponenten neu im React-Ökosystem sind, unterstützt Jest diese derzeit nicht. Während Sie weiterhin Unit-Tests für synchrone Server- und Client-Komponenten ausführen können, empfehlen wir E2E-Tests für async-Komponenten.

Schnellstart

Sie können create-next-app mit dem Next.js with-jest Beispiel verwenden, um schnell zu beginnen:

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

Manuelle Einrichtung

Seit der Veröffentlichung von Next.js 12 verfügt Next.js über eine integrierte Konfiguration für Jest.

Um Jest einzurichten, installieren Sie jest und die folgenden Pakete als Entwicklungsabhängigkeiten:

Terminal
npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node
# oder
yarn add -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node
# oder
pnpm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node

Generieren Sie eine grundlegende Jest-Konfigurationsdatei, indem Sie den folgenden Befehl ausführen:

Terminal
npm init jest@latest
# oder
yarn create jest@latest
# oder
pnpm create jest@latest

Dies führt Sie durch eine Reihe von Eingabeaufforderungen zur Einrichtung von Jest für Ihr Projekt, einschließlich automatischer Erstellung einer jest.config.ts|js-Datei.

Aktualisieren Sie Ihre Konfigurationsdatei für die Verwendung von next/jest. Dieser Transformer enthält alle notwendigen Konfigurationsoptionen, damit Jest mit Next.js funktioniert:

jest.config.ts
import type { Config } from 'jest'
import nextJest from 'next/jest.js'
 
const createJestConfig = nextJest({
  // Geben Sie den Pfad zu Ihrer Next.js-App an, um next.config.js und .env-Dateien in Ihrer Testumgebung zu laden
  dir: './',
})
 
// Fügen Sie eine benutzerdefinierte Konfiguration hinzu, die an Jest übergeben werden soll
const config: Config = {
  coverageProvider: 'v8',
  testEnvironment: 'jsdom',
  // Fügen Sie weitere Einrichtungsoptionen hinzu, bevor jeder Test ausgeführt wird
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}
 
// createJestConfig wird auf diese Weise exportiert, um sicherzustellen, dass next/jest die Next.js-Konfiguration laden kann, die asynchron ist
export default createJestConfig(config)
jest.config.js
const nextJest = require('next/jest')
 
/** @type {import('jest').Config} */
const createJestConfig = nextJest({
  // Geben Sie den Pfad zu Ihrer Next.js-App an, um next.config.js und .env-Dateien in Ihrer Testumgebung zu laden
  dir: './',
})
 
// Fügen Sie eine benutzerdefinierte Konfiguration hinzu, die an Jest übergeben werden soll
const config = {
  coverageProvider: 'v8',
  testEnvironment: 'jsdom',
  // Fügen Sie weitere Einrichtungsoptionen hinzu, bevor jeder Test ausgeführt wird
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}
 
// createJestConfig wird auf diese Weise exportiert, um sicherzustellen, dass next/jest die Next.js-Konfiguration laden kann, die asynchron ist
module.exports = createJestConfig(config)

Im Hintergrund konfiguriert next/jest Jest automatisch, einschließlich:

  • Einrichten von transform mit dem Next.js Compiler
  • Automatisches Mocken von Stylesheets (.css, .module.css und deren scss-Varianten), Bildimporten und next/font
  • Laden von .env (und allen Varianten) in process.env
  • Ignorieren von node_modules bei Test-Auflösung und -Transformationen
  • Ignorieren von .next bei Test-Auflösung
  • Laden von next.config.js für Flags, die SWC-Transformationen aktivieren

Hinweis: Um Umgebungsvariablen direkt zu testen, laden Sie diese manuell in einem separaten Setup-Skript oder in Ihrer jest.config.ts-Datei. Weitere Informationen finden Sie unter Test-Umgebungsvariablen.

Jest-Einrichtung (mit Babel)

Wenn Sie den Next.js Compiler deaktivieren und stattdessen Babel verwenden, müssen Sie Jest manuell konfigurieren und zusätzlich zu den oben genannten Paketen babel-jest und identity-obj-proxy installieren.

Hier sind die empfohlenen Optionen zur Konfiguration von Jest für Next.js:

jest.config.js
module.exports = {
  collectCoverage: true,
  // auf Node 14.x bietet der Coverage-Provider v8 eine gute Geschwindigkeit und mehr oder weniger guten Bericht
  coverageProvider: 'v8',
  collectCoverageFrom: [
    '**/*.{js,jsx,ts,tsx}',
    '!**/*.d.ts',
    '!**/node_modules/**',
    '!<rootDir>/out/**',
    '!<rootDir>/.next/**',
    '!<rootDir>/*.config.js',
    '!<rootDir>/coverage/**',
  ],
  moduleNameMapper: {
    // CSS-Importe behandeln (mit CSS-Modulen)
    // https://jestjs.io/docs/webpack#mocking-css-modules
    '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
 
    // CSS-Importe behandeln (ohne CSS-Module)
    '^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js',
 
    // Bildimporte behandeln
    // https://jestjs.io/docs/webpack#handling-static-assets
    '^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$': `<rootDir>/__mocks__/fileMock.js`,
 
    // Modulaliase behandeln
    '^@/components/(.*)$': '<rootDir>/components/$1',
 
    // @next/font behandeln
    '@next/font/(.*)': `<rootDir>/__mocks__/nextFontMock.js`,
    // next/font behandeln
    'next/font/(.*)': `<rootDir>/__mocks__/nextFontMock.js`,
    // Server-only deaktivieren
    'server-only': `<rootDir>/__mocks__/empty.js`,
  },
  // Weitere Einrichtungsoptionen hinzufügen, bevor jeder Test ausgeführt wird
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
  testEnvironment: 'jsdom',
  transform: {
    // Verwenden Sie babel-jest, um Tests mit der next/babel-Voreinstellung zu transpilieren
    // https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
    '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
  },
  transformIgnorePatterns: [
    '/node_modules/',
    '^.+\\.module\\.(css|sass|scss)$',
  ],
}

Sie können mehr über jede Konfigurationsoption in der Jest-Dokumentation erfahren. Wir empfehlen auch, die next/jest-Konfiguration zu überprüfen, um zu sehen, wie Next.js Jest konfiguriert.

Stylesheets und Bildimporte behandeln

Stylesheets und Bilder werden in Tests nicht verwendet, aber ihr Import kann Fehler verursachen, daher müssen sie gemockt werden.

Erstellen Sie die in der Konfiguration genannten Mock-Dateien - fileMock.js und styleMock.js - in einem __mocks__-Verzeichnis:

__mocks__/fileMock.js
module.exports = 'test-file-stub'
__mocks__/styleMock.js
module.exports = {}

Weitere Informationen zum Umgang mit statischen Assets finden Sie in der Jest-Dokumentation.

Schriftarten behandeln

Um Schriftarten zu behandeln, erstellen Sie die Datei nextFontMock.js im __mocks__-Verzeichnis und fügen Sie die folgende Konfiguration hinzu:

__mocks__/nextFontMock.js
module.exports = new Proxy(
  {},
  {
    get: function getter() {
      return () => ({
        className: 'className',
        variable: 'variable',
        style: { fontFamily: 'fontFamily' },
      })
    },
  }
)

Optional: Absolute Importe und Modul-Pfadalias behandeln

Wenn Ihr Projekt Modul-Pfadalias verwendet, müssen Sie Jest so konfigurieren, dass die Importe aufgelöst werden, indem Sie die Pfadoption in der jsconfig.json-Datei mit der moduleNameMapper-Option in der jest.config.js-Datei abgleichen. Beispiel:

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

Optional: Jest mit benutzerdefinierten Matchern erweitern

@testing-library/jest-dom enthält einen Satz praktischer benutzerdefinierter Matcher wie .toBeInTheDocument(), die das Schreiben von Tests vereinfachen. Sie können die benutzerdefinierten Matcher für jeden Test importieren, indem Sie die folgende Option zur Jest-Konfigurationsdatei hinzufügen:

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

Fügen Sie dann in jest.setup.ts den folgenden Import hinzu:

jest.setup.ts
import '@testing-library/jest-dom'
jest.setup.js
import '@testing-library/jest-dom'

Hinweis: extend-expect wurde in v6.0 entfernt. Wenn Sie @testing-library/jest-dom vor Version 6 verwenden, müssen Sie stattdessen @testing-library/jest-dom/extend-expect importieren.

Wenn Sie weitere Setup-Optionen vor jedem Test hinzufügen müssen, können Sie diese zur obigen jest.setup.js-Datei hinzufügen.

Ein Test-Skript zu package.json hinzufügen:

Fügen Sie schließlich ein Jest-test-Skript zu Ihrer package.json-Datei hinzu:

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

jest --watch führt Tests erneut aus, wenn eine Datei geändert wird. Weitere Jest-CLI-Optionen finden Sie in der Jest-Dokumentation.

Ihren ersten Test erstellen:

Ihr Projekt ist jetzt bereit, Tests auszuführen. Erstellen Sie einen Ordner namens __tests__ im Stammverzeichnis Ihres Projekts.

Zum Beispiel können wir einen Test hinzufügen, um zu überprüfen, ob die <Home />-Komponente erfolgreich eine Überschrift rendert:

pages/index.js
export default function Home() {
  return <h1>Home</h1>
}
__tests__/index.test.js
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import Home from '../pages/index'
 
describe('Home', () => {
  it('renders a heading', () => {
    render(<Home />)
 
    const heading = screen.getByRole('heading', { level: 1 })
 
    expect(heading).toBeInTheDocument()
  })
})

Optional können Sie einen Snapshot-Test hinzufügen, um unerwartete Änderungen in Ihrer Komponente zu verfolgen:

__tests__/snapshot.js
import { render } from '@testing-library/react'
import Home from '../pages/index'
 
it('renders homepage unchanged', () => {
  const { container } = render(<Home />)
  expect(container).toMatchSnapshot()
})

Hinweis: Testdateien sollten nicht im Pages Router enthalten sein, da alle Dateien im Pages Router als Routen betrachtet werden.

Tests ausführen

Führen Sie dann den folgenden Befehl aus, um Ihre Tests auszuführen:

Terminal
npm run test
# oder
yarn test
# oder
pnpm test

Zusätzliche Ressourcen

Für weitere Informationen können diese Ressourcen hilfreich sein: