Vitest y Node test runner

Avanzado
JavaScript
JavaScript
Actualizado: 18/04/2026

Panorama del testing moderno en JavaScript

El ecosistema de testing en JavaScript ha evolucionado desde que Jest se convirtió en el estándar de facto. Hoy hay dos alternativas modernas que están reemplazando a Jest en muchos proyectos: Vitest, que aprovecha la infraestructura de Vite para arrancar tests a una velocidad notable, y el runner nativo de Node.js, disponible en el módulo node:test sin instalar nada adicional.

Ambas herramientas resuelven problemas que Jest heredó por su edad: configuración compleja para ESM, dificultad con proyectos TypeScript puros, arranque lento cuando hay muchos tests y necesidad de transformadores intermedios. En 2026 son la elección recomendada para proyectos nuevos.

La regla general es usar Vitest si el proyecto ya usa Vite o necesitas un runner rico en features, y el runner nativo si el objetivo es minimizar dependencias en una librería o script.

Qué ofrece cada opción

Vitest es un test runner compatible a nivel de API con Jest en la mayoría de casos. Soporta ESM de forma nativa, TypeScript sin configuración, JSX y Vue, ejecuta suites en paralelo por defecto y ofrece una UI web para inspeccionar tests. Se integra con Vite, por lo que la configuración de alias, plugins y variables de entorno se reutiliza.

El runner nativo de Node vive en node:test y las aserciones en node:assert. No tiene opinión sobre coverage, mocks o reportes: es un punto de partida ligero. Desde la versión 22, soporta watch mode, filtros por nombre y lifecycle hooks como beforeEach.

graph LR
    A[Proyecto JavaScript] --> B{Necesidades}
    B -->|Rico en features, UI, Vite| C[Vitest]
    B -->|Mnimas dependencias, librera| D[node:test]
    C --> E[npm install -D vitest]
    D --> F[node --test]
    E --> G[Tests con describe/it/expect]
    F --> H[Tests con node:assert]

Primeros pasos con Vitest

La instalación de Vitest es una dependencia de desarrollo. No necesita configuración adicional si el proyecto ya usa Vite; si no, funciona con un archivo mínimo.

npm install -D vitest

Anade un script en package.json para lanzar los tests. El comando vitest arranca en modo watch por defecto, y vitest run ejecuta los tests una sola vez (típico para CI).

{
    "scripts": {
        "test": "vitest",
        "test:run": "vitest run",
        "test:coverage": "vitest run --coverage"
    }
}

Los archivos de test siguen la convención *.test.js o *.spec.js. Vitest los encuentra automáticamente dentro del proyecto. La API principal es muy similar a Jest.

// suma.js
export function suma(a, b) {
    return a + b;
}
// suma.test.js
import { describe, test, expect } from "vitest";
import { suma } from "./suma.js";

describe("suma", () => {
    test("suma dos enteros positivos", () => {
        expect(suma(2, 3)).toBe(5);
    });

    test("suma cero y un numero", () => {
        expect(suma(0, 7)).toBe(7);
    });
});

La compatibilidad de API con Jest significa que migrar un proyecto existente es en muchos casos cambiar el paquete y retocar configuración, sin reescribir tests.

Hooks, mocks y spies en Vitest

Vitest incluye hooks de ciclo de vida familiares: beforeAll, afterAll, beforeEach y afterEach. Los mocks se crean con vi.fn(), equivalente a jest.fn(), y los módulos se pueden reemplazar con vi.mock().

import { describe, test, expect, vi, beforeEach } from "vitest";
import { procesarPago } from "./pagos.js";

describe("procesarPago", () => {
    let apiMock;

    beforeEach(() => {
        apiMock = vi.fn().mockResolvedValue({ ok: true, id: "tx_123" });
    });

    test("devuelve el id de la transaccion", async () => {
        const resultado = await procesarPago({ importe: 100 }, apiMock);
        expect(resultado.id).toBe("tx_123");
        expect(apiMock).toHaveBeenCalledOnce();
    });
});

El modo UI se activa con npm install -D @vitest/ui y el flag --ui. Abre una interfaz web que muestra el arbol de tests, permite filtrar y relanza suites individuales, algo muy útil en proyectos grandes.

Cobertura y configuracion

La cobertura con Vitest usa v8 internamente. Se instala como dependencia opcional y se activa con --coverage.

npm install -D @vitest/coverage-v8
npm run test:coverage

Para personalizar exclusiones o umbrales, se crea un archivo vitest.config.ts (o .js). Los alias de Vite se comparten automáticamente.

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

export default defineConfig({
    test: {
        environment: "node",
        coverage: {
            provider: "v8",
            thresholds: {
                lines: 80,
                functions: 80,
                branches: 75,
                statements: 80
            },
            exclude: ["**/node_modules/**", "**/dist/**"]
        }
    }
});

El test runner nativo de Node.js

El runner integrado en Node no requiere instalar nada. Se usa el módulo node:test para definir suites y node:assert para aserciones. La ejecución se hace con el flag --test.

// matematicas.test.js
import { test, describe } from "node:test";
import assert from "node:assert/strict";
import { suma } from "./suma.js";

describe("suma", () => {
    test("suma positivos", () => {
        assert.equal(suma(2, 3), 5);
    });

    test("suma con cero", () => {
        assert.equal(suma(0, 7), 7);
    });
});

La ejecución se lanza desde la linea de comandos. Node detecta los archivos con patrones como *.test.js, test.js o los archivos dentro de test/.

node --test
node --test --watch       # Modo observador
node --test --only        # Solo tests marcados con only

El runner nativo es ideal para librerías sin build donde cada dependencia adicional es un compromiso de mantenimiento.

Aserciones con node:assert

El módulo node:assert/strict ofrece las aserciones más usadas con comparaciones estrictas por defecto. La versión /strict equivale a usar === donde Jest o Vitest usarían toBe.

import assert from "node:assert/strict";

assert.equal(valor, esperado);            // Igual con ===
assert.deepEqual(obj, esperado);          // Estructura profunda
assert.ok(condicion);                     // Truthy
assert.throws(() => fn(), /mensaje/);     // Lanza con mensaje
await assert.rejects(async () => fn());   // Promesa rechazada

Para mocks, desde Node 22 existe mock.fn() y mock.method() en el propio módulo node:test. No es tan rico como Vitest pero cubre casos simples.

import { test, mock } from "node:test";
import assert from "node:assert/strict";

test("registra llamadas con mock.fn", () => {
    const log = mock.fn();
    log("hola");
    log("mundo");
    assert.equal(log.mock.calls.length, 2);
    assert.equal(log.mock.calls[0].arguments[0], "hola");
});

Reporters y salida

Node admite varios reporters. El reporter spec muestra salida legible; tap produce el formato estándar Test Anything Protocol; dot es compacto para CI.

node --test --test-reporter=spec
node --test --test-reporter=tap > resultados.tap

Combinar --experimental-test-coverage con un reporter permite medir cobertura sin herramientas externas, aunque los reportes son más básicos que los de v8 a través de Vitest.

Migración y coexistencia

Un proyecto existente con Jest puede migrar a Vitest en una tarde para la mayoría de suites. Las diferencias típicas son: jest.fn() pasa a vi.fn(), jest.mock() a vi.mock(), y algunos matchers específicos pueden requerir ajustes menores.

// Antes (Jest)
jest.mock("./api");
const { crear } = require("./servicio");

// Despues (Vitest)
import { vi } from "vitest";
vi.mock("./api");
import { crear } from "./servicio.js";

Cuando el proyecto es una librería publicada en npm, el runner nativo es una opción atractiva porque no anade dependencias al consumidor ni al repositorio. Para aplicaciones frontend o proyectos con build tooling, Vitest encaja mejor por su integración con Vite y la UI interactiva.

La decisión final depende del contexto: volumen de tests, experiencia del equipo con Jest, y si el proyecto ya usa Vite. En cualquier caso, ambas opciones son más rápidas y menos complicadas de configurar que Jest en proyectos modernos.

Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, JavaScript es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de JavaScript

Explora más contenido relacionado con JavaScript y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Configurar Vitest en un proyecto Vite o Node. Usar el test runner nativo de Node.js. Escribir tests con describe, test y expect. Ejecutar suites en paralelo y en modo watch. Generar coverage con c8 integrado.