Test Runner

Vitest

Vitest es el ejecutor de pruebas rápido y nativo de Vite. Reutiliza tu configuración de build, ejecuta pruebas en paralelo y ofrece APIs compatibles con Jest con soporte de primer nivel para TypeScript.

intermediate13 min readUpdated 15 sept 2026
sum.test.ts
ts
// sum.test.ts
import { describe, it, expect } from "vitest";
import { sum } from "./sum";

describe("sum", () => {
  it("adds two numbers", () => {
    expect(sum(2, 3)).toBe(5);
  });

  it("handles negatives", () => {
    expect(sum(-1, -1)).toBe(-2);
  });
});
Impulsado por
Vite
API
Compatible con Jest
Lenguaje
TypeScript nativo
Mocks
vi.fn, vi.mock
Modo Watch
Instantáneo, Vite HMR
Modo Navegador
Pruebas en navegador real

Por que importa

Por qué Vitest está ganando

Rápido por defecto

Las pruebas se ejecutan a través del pipeline de transformación de Vite en workers paralelos, por lo que el feedback es casi instantáneo incluso en suites grandes.

Reutiliza tu configuración

Los alias, plugins y ajustes de TypeScript provienen de la misma configuración de Vite que ya usa tu aplicación, por lo que no hay nada que duplicar.

API compatible con Jest

describe, it, expect y los helpers de mocking reflejan a Jest, lo que hace que la migración y el conocimiento compartido sean sencillos.

La imagen completa

Las tres ideas detrás de Vitest

Un pipeline nativo de Vite, una API compatible con Jest y workers en paralelo que mantienen el ciclo de feedback rápido.

El ejecutor

Ejecutar

Busca archivos de prueba, los ejecuta en workers paralelos y reporta los resultados con una UI clara y rápida.

La transformación

Construir

Usa Vite para compilar TypeScript, JSX y alias exactamente igual que lo hace tu aplicación.

Aserciones y mocks

Verificar

expect, vi.fn y vi.mock cubren las aserciones, spies y el mocking de módulos.

Vitest de un vistazo

El núcleo de Vitest

describe e it

Agrupa pruebas relacionadas y nombra cada una según el comportamiento que verifica.

expect

Una API de matchers rica para valores, objetos, errores y resultados asíncronos.

vi.fn y vi.spyOn

Crea mocks y spies para aislar el código bajo prueba.

vi.mock

Reemplaza un módulo completo con un mock, elevado (hoisted) por encima de los imports.

Pruebas asíncronas

Usa await con promesas y emplea expect.resolves o expect.rejects.

Cobertura y UI

Reportes de cobertura integrados y una UI de navegador opcional.

Una breve historia

Un ejecutor de pruebas construido para Vite

  1. 2021

    Anuncio de Vitest

    Anthony Fu presenta un ejecutor de pruebas nativo de Vite que reutiliza el pipeline existente.

    21
  2. 2022

    Bases de Vitest 1.0

    Lanzamientos rápidos añaden cobertura, modo navegador y compatibilidad con Jest.

    22
  3. 2024

    Vitest 1 y 2

    Una API estable, proyectos de workspace y la maduración del modo navegador.

    24
  4. Hoy

    El estándar para Vite

    El ejecutor de pruebas recomendado para Vite, Vue, Svelte, Solid y muchas configuraciones de React.

    Hoy

La guia completa

Vitest: Todo lo que necesitas saber

¿Qué es Vitest?

Vitest es un test runner impulsado por Vite. Reutiliza tu configuración de Vite actual —alias, plugins, transformaciones de TypeScript y JSX— para que las pruebas se ejecuten a través del mismo pipeline que tu aplicación. Esa base compartida es la razón por la cual inicia rápido y se mantiene rápido.

La API te resultará familiar si has utilizado Jest. describe, it, expect y los helpers de mocking funcionan de la misma manera. Lo que cambia es el motor interno: Vitest ejecuta las pruebas en workers en paralelo, monitorea los archivos con el grafo de módulos de Vite y ofrece soporte nativo para TypeScript sin necesidad de configuración adicional.

Escribiendo tu primera prueba

Un archivo de prueba importa desde vitest y describe el comportamiento que verifica.

// sum.test.ts
import { describe, it, expect } from "vitest";
import { sum } from "./sum";

describe("sum", () => {
  it("adds two numbers", () => {
    expect(sum(2, 3)).toBe(5);
  });

  it("handles negatives", () => {
    expect(sum(-1, -1)).toBe(-2);
  });
});

Nombra las pruebas según el comportamiento, no según la función. Una prueba fallida que diga “suma dos números” te indica qué se rompió; una que diga “prueba de suma 1” no lo hace. Agrupa los casos relacionados con describe y utiliza beforeEach y afterEach para la configuración y limpieza.

Assertions

Vitest incluye una API de matchers muy completa, similar a la de Jest.

// assertions.test.ts
expect(value).toBe(5);              // strict equality
expect(value).toEqual({ a: 1 });    // deep equality
expect(value).toBeTruthy();
expect(list).toHaveLength(3);
expect(list).toContain("a");
expect(fn).toThrow("invalid");
expect(value).toBeGreaterThan(3);

Usa toEqual para objetos y arrays, y toBe para primitivos y comprobaciones de referencia. toMatchObject y toContainEqual son útiles cuando solo te interesa una parte de una estructura.

Mocks y spies

El aislamiento es fundamental para las pruebas unitarias. Vitest proporciona vi.fn para mocks, vi.spyOn para envolver métodos existentes y vi.mock para reemplazar módulos completos.

// api.test.ts
import { vi, describe, it, expect } from "vitest";
import { fetchUser } from "./api";

vi.mock("./http", () => ({
  get: vi.fn().mockResolvedValue({ id: 1, name: "Ada" }),
}));

describe("fetchUser", () => {
  it("returns the user", async () => {
    await expect(fetchUser(1)).resolves.toEqual({ id: 1, name: "Ada" });
  });
});

vi.mock se eleva (hoisting) por encima de los imports, por lo que el mock se registra antes de que el módulo bajo prueba lo cargue. Cuando la factory necesita una variable definida en el archivo de prueba, utiliza vi.hoisted para que el valor exista antes de que se ejecute el mock.

Pruebas asíncronas

Espera a que la operación finalice y realiza la aserción sobre el resultado. Vitest proporciona los helpers resolves y rejects para promesas.

// async.test.ts
it("rejects on failure", async () => {
  await expect(loadUser(-1)).rejects.toThrow("Invalid id");
});

Prioriza este estilo sobre el callback done. Olvidar llamar a done provoca timeouts difíciles de diagnosticar, y las promesas rechazadas no gestionadas pueden filtrarse entre las pruebas. Para los timers falsos, vi.useFakeTimers() y vi.advanceTimersByTime() te permiten probar debounces e intervalos de manera determinista.

Snapshots

Los snapshots capturan un valor y lo comparan en ejecuciones posteriores. Son útiles para salidas extensas y estables, como datos serializados o markup renderizado, pero son fáciles de usar incorrectamente.

// snapshot.test.ts
it("matches the shape", () => {
  expect(createConfig({ debug: true })).toMatchSnapshot();
});

Un snapshot que se actualiza sin ser revisado es peor que no tener ningún test. Utilízalos para estructuras de datos donde una comparación completa sea impráctica, y prefiere aserciones explícitas cuando sepas exactamente qué es lo importante. toMatchInlineSnapshot mantiene el valor esperado dentro del archivo del test, lo que hace que las revisiones sean significativas.

Configuración

Vitest lee un bloque test de tu configuración de Vite o de un vitest.config.ts dedicado.

// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    environment: "jsdom",
    globals: true,
    coverage: {
      provider: "v8",
      reporter: ["text", "html"],
      thresholds: { lines: 80 },
    },
  },
});

La opción environment permite seleccionar node, jsdom, happy-dom o un navegador. Para pruebas de componentes, lo habitual es usar jsdom o happy-dom; para lógica pura, mantén el entorno rápido de node. Los umbrales de cobertura (coverage thresholds) convierten un objetivo de cobertura en una regla obligatoria.

Vitest y la pirámide de pruebas

Vitest es la capa de pruebas unitarias y de integración. Combínalo con una librería de pruebas de componentes como Testing Library para el comportamiento de la UI, y con una herramienta de end-to-end como Playwright para los flujos completos de usuario. Juntos cubren la pirámide: muchas pruebas unitarias rápidas, menos pruebas de integración y un puñado de pruebas end-to-end.

Mejores prácticas

  • Prueba el comportamiento, no los detalles de la implementación.
  • Mantén cada prueba enfocada en un solo comportamiento.
  • Usa beforeEach para la configuración compartida y limpia los mocks con vi.clearAllMocks.
  • Prefiere resolves y rejects sobre los callbacks de done.
  • Haz mock en los límites (red, tiempo, aleatoriedad), no de cada llamada interna.
  • Usa umbrales de cobertura para evitar regresiones silenciosas.
  • Ejecuta en modo watch durante el desarrollo y en CI en cada push.

Errores comunes

  • Hacer aserciones sobre el estado interno o métodos privados en lugar del comportamiento observable.
  • Actualizar snapshots sin revisar el diff.
  • Olvidar limpiar los mocks entre tests, provocando fugas de estado.
  • Usar timers reales, lo que vuelve los tests lentos e inestables (flaky).
  • Excederse con los mocks hasta que el test solo verifica los propios mocks.
  • Probar el mismo comportamiento en cada nivel de la pirámide.

Próximos pasos

Vitest es la forma más rápida de empezar a testear un proyecto de Vite. Compáralo con el clásico Jest, añade Testing Library para los componentes y Playwright para los flujos end-to-end, y apóyate en Vite para mantener la configuración compartida. Después, escribe algunas pruebas para el código que ya tienes y observa cómo hacer un refactor se vuelve un proceso seguro.

Probar código asíncrono

Usa await para la promesa y haz la aserción sobre el resultado. El callback done es fácil de olvidar y produce timeouts confusos.

Preferido
it("loads the user", async () => {
  await expect(getUser(1)).resolves.toEqual({
    id: 1,
    name: "Ada",
  });
});
Evitar
it("loads the user", (done) => {
  getUser(1).then((user) => {
    expect(user.name).toBe("Ada");
    done();
  });
});

Mocking de un módulo

vi.mock se eleva (hoist) por encima de los imports, por lo que el módulo se reemplaza antes de que el código bajo prueba lo cargue.

Preferido
import { vi } from "vitest";

vi.mock("./api", () => ({
  fetchUser: vi.fn().mockResolvedValue({
    id: 1,
  }),
}));
Evitar
import * as api from "./api";
// reassigning after import
// is brittle and often fails
api.fetchUser = async () => ({ id: 1 });

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Vitest?

Nuestro tutorial interactivo te guia a traves de Vitest paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.