Configuración de Vitest con Next.js
Configura Vitest como un runner de tests rápido y moderno para tu proyecto de Next.js con App Router.
Busca en todas las páginas de la documentación
Configura Vitest como un runner de tests rápido y moderno para tu proyecto de Next.js con App Router.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Tarjeta de referencia rápida - lista para copiar y pegar.
# Instalar dependencias
npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event// vitest.config.ts
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
import path from "path";
export default defineConfig({
plugins: [react()],
test: {
environment: "jsdom",
globals: true,
setupFiles: ["./vitest.setup.ts"],
include: ["**/*.test.{ts,tsx}"],
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});// vitest.setup.ts
import "@testing-library/jest-dom/vitest";// scripts de package.json
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage"
}
}Cuándo usarlo: Cuando empiezas un proyecto nuevo de Next.js y quieres un runner de tests rápido y nativo de Vite con un modo watch casi instantáneo basado en HMR.
// src/components/greeting.tsx
interface GreetingProps {
name: string;
}
export function Greeting({ name }: GreetingProps) {
return <h1>Hello, {name}!</h1>;
}// src/components/greeting.test.tsx
import { render, screen } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import { Greeting } from "./greeting";
describe("Greeting", () => {
it("renders the name", () => {
render(<Greeting name="Alice" />);
expect(screen.getByRole("heading")).toHaveTextContent("Hello, Alice!");
});
it("updates when name prop changes", () => {
const { rerender } = render(<Greeting name="Alice" />);
expect(screen.getByRole("heading")).toHaveTextContent("Hello, Alice!");
rerender(<Greeting name="Bob" />);
expect(screen.getByRole("heading")).toHaveTextContent("Hello, Bob!");
});
});Lo que demuestra:
@/ de tsconfig@vitejs/plugin-react sin necesidad de una configuración de Babel aparteenvironment: "jsdom" crea un DOM de navegador simulado en Node.js para cada archivo de testglobals: true hace que describe, it y expect estén disponibles sin importarlos (siguiendo las convenciones de Jest)@testing-library/jest-dom/vitest añade matchers como toBeInTheDocument() y toHaveTextContent()Usar happy-dom en lugar de jsdom:
// vitest.config.ts
export default defineConfig({
test: {
environment: "happy-dom", // faster but less complete DOM implementation
},
});Anulación del entorno por archivo:
// @vitest-environment happy-dom
import { describe, it } from "vitest";
// This file uses happy-dom regardless of global configCobertura con el proveedor v8:
npm install -D @vitest/coverage-v8// vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: "v8",
reporter: ["text", "html", "lcov"],
include: ["src/**/*.{ts,tsx}"],
exclude: ["src/**/*.test.{ts,tsx}", "src/**/*.d.ts"],
},
},
});Alias de rutas del App Router desde tsconfig:
// vitest.config.ts - match tsconfig paths exactly
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [react(), tsconfigPaths()],
test: {
environment: "jsdom",
globals: true,
setupFiles: ["./vitest.setup.ts"],
},
});npm install -D vite-tsconfig-paths// If using globals: true, add vitest types to tsconfig
// tsconfig.json
{
"compilerOptions": {
"types": ["vitest/globals", "@testing-library/jest-dom"]
}
}Falta @vitejs/plugin-react - Sin este plugin, el JSX en los archivos de test no se transforma. Vitest no gestiona JSX automáticamente como Jest con Babel. Solución: Incluye siempre react() en el array de plugins.
Los alias de rutas no se resuelven - Si usas importaciones @/components/..., Vitest no lee las rutas de tsconfig.json por defecto. Solución: Define alias manualmente en vitest.config.ts o usa vite-tsconfig-paths.
globals: true pero errores de TypeScript - TypeScript no conoce los globals de Vitest a menos que añadas "vitest/globals" a compilerOptions.types. Solución: Actualiza tsconfig.json como se muestra arriba.
jsdom vs happy-dom - happy-dom es más rápido pero carece de algunas APIs de DOM (getBoundingClientRect, IntersectionObserver). Si los tests fallan con happy-dom, cambia a jsdom.
Código exclusivo del servidor de Next.js - Vitest no puede ejecutar código que use next/headers, next/cache u otras APIs de Next.js solo para Node en un entorno jsdom. Solución: Simula esos módulos o pruébalos por separado.
| Alternativa | Úsala cuando | No la uses cuando |
|---|---|---|
Jest con next/jest | Ya tienes una configuración de Jest o necesitas el ecosistema más amplio de Jest | Quieres un modo watch más rápido y soporte ESM nativo |
| Playwright Component Testing | Necesitas renderizado en un navegador real para tests de componentes | Quieres tests unitarios rápidos que se ejecuten en Node |
| Bun test runner | Tu proyecto usa Bun como runtime | Necesitas el ecosistema de matchers y plugins de Vitest/Jest |
react(), cualquier JSX en archivos de test o de código fuente fallará al compilar.react() en el array plugins de vitest.config.ts.jsdom es una implementación de DOM de navegador más completa, pero más lenta.happy-dom es más rápido pero carece de algunas APIs como getBoundingClientRect e IntersectionObserver.happy-dom, cambia a jsdom.Establece globals: true en vitest.config.ts y añade "vitest/globals" al array compilerOptions.types de tu tsconfig.json.
@testing-library/jest-dom/vitest añade matchers como toBeInTheDocument() y toHaveTextContent().Define alias manualmente en vitest.config.ts:
alias: {
"@": path.resolve(__dirname, "./src"),
}O instala y usa vite-tsconfig-paths como plugin.
globals: true los hace disponibles en tiempo de ejecución, pero TypeScript no los conoce."vitest/globals" a compilerOptions.types en tsconfig.json.npm install -D @vitest/coverage-v8Luego añade coverage.provider: "v8" y los reporters que quieras en vitest.config.ts.
Sí. Añade un comentario al inicio del archivo de test:
// @vitest-environment happy-domEsto anula la configuración global del entorno solo para ese archivo.
jsdom.Importa defineConfig desde vitest/config:
import { defineConfig } from "vitest/config";
export default defineConfig({ /* ... */ });Esto te da comprobación de tipos completa y autocompletado para todas las opciones de configuración de Vitest.
vitest inicia el modo watch, volviendo a ejecutar los tests cuando cambian los archivos.vitest run ejecuta todos los tests una vez y termina - úsalo en CI.Usa el grafo de módulos de Vite para rastrear dependencias. Solo se vuelven a ejecutar los tests afectados por los archivos modificados, lo que lo hace mucho más rápido que el modo watch de Jest.
Revisado por Chris St. John·Última actualización: 10 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥