Saltar al contenido principal

Pruebas unitarias de JavaScript: Guía integral 2026

Domina las pruebas unitarias de javascript con nuestra guía de 2026. Cubre Jest, Mocha, configuración, simulación, CI y consejos para Capacitor & aplicaciones de Electron.

Martin Donadieu

Martin Donadieu

Content Marketer

Guía Integral de Pruebas de JavaScript: 2026

Probablemente estás en una de dos situaciones en este momento. O tu proyecto de JavaScript tiene casi ninguna prueba y cada refactor se siente arriesgado, o ya tienes pruebas y la mitad de ellas son lentas, frágiles y extrañamente difíciles de confiar.

Que empeora en Capacitor y aplicaciones de Electron. Una característica simple puede afectar la lógica empresarial compartida, las API del navegador, los plugins nativos, los archivos locales, la comunicación interprocesos y los servicios remotos en el mismo flujo. Si pruebas esas piezas de manera incorrecta, tu conjunto de pruebas se convierte en un laberinto de dependencias falsas. Si las pruebas de manera correcta, obtienes feedback rápido sobre la lógica que se rompe. Las buenas pruebas unitarias de JavaScript no comienzan con la sintaxis de los matchers inteligentes. Comienza con una frontera disciplinada: prueba la lógica pura directamente, aísla los efectos laterales y evita escribir pruebas que se derrumben en el momento en que renombres una función interna.

Índice

Elección de tu marco de pruebas de JavaScript

Elegir tu framework de pruebas de JavaScript

Un proyecto de JavaScript profesional necesita un verdadero ejecutor de tests. Los scripts ad hoc y las comprobaciones manuales de la consola no escalan cuando varios ingenieros tocan el mismo códigobase. Necesitas descubrimiento de tests, afirmaciones, manejo de sincronía, mocks y una forma de ejecutar todo de manera consistente en desarrollo local y CI.

La orientación actual converge en un conjunto pequeño de opciones principales. Jest, Mocha y Jasmine son destacados repetidamente como los marcos primarios, con Jest que a menudo se destaca por su estructura de prueba integrada, afirmaciones, simulación y soporte asíncrono en un paquete, como se muestra en este lab de prueba de JavaScript de Pluralsight.

Una tabla de comparación que muestra los marcos de prueba de JavaScript populares, incluyendo Jest, Mocha, Cypress y Playwright.

¿Por qué un marco no es opcional?

El primer error que cometen los equipos es tratar las pruebas unitarias como una actividad secundaria. Eso suele llevar a nombres de archivo inconsistentes, afirmaciones personalizadas que nadie recuerda y ayudantes que solo entiende una persona.

Un marco te da un lenguaje compartido:

  • Estructura de prueba con __CAPGO_KEEP_0__ describe y test o it
  • Assertions con matchers legibles
  • Hooks para la configuración y el desmantelamiento
  • Soporte asíncrono para promesas y temporizadores
  • Herramientas de simulación para dependencias externas

Si su equipo también necesita una visión más amplia de la automatización de pruebas más allá del trabajo a nivel de unidad, Capgo tiene una útil visión general de pruebas automatizadas en flujos de entrega de aplicaciones.

Jest vs Mocha a primera vista

Jest y Mocha representan dos filosofías diferentes.

Jest es la opción todo en uno. Lleva la mayoría de lo que las equipos necesitan desde el primer día.
Mocha es más modular. Te da un ejecutor y espera que assembles el resto de la pila.

CaracterísticaJestMocha
Complejidad de configuraciónMenor para la mayoría de los equiposMayor porque sueles agregar bibliotecas de afirmación y simulación
DeclaracionesIntegradoNormalmente se combina con otra biblioteca
SimulaciónIntegradoNormalmente se combina con otra biblioteca
Pruebas asíncronasIntegrado y directoSoportado, pero depende más de la configuración circundante
Flujo de coberturaComúnmente integrado en el mismo conjunto de herramientasA menudo más ensamblado
Mejor ajusteNuevos proyectos, equipos que buscan coherenciaPilas de legado, equipos que buscan control modular

Regla práctica: Si su equipo tiene que preguntar cuál es la biblioteca de afirmaciones y cuál es la biblioteca de simulación que se deben combinar con el ejecutor, probablemente querrá Jest.

Lo que recomiendo para la mayoría de los equipos

Para la mayoría de los proyectos modernos, elijo Jest a menos que el código base ya tenga razones fuertes para mantenerse en Mocha. Esa recomendación se vuelve más fuerte cuando la aplicación incluye Capacitor o Electronporque esos proyectos ya tienen suficientes partes en movimiento. Reducir la dispersión de herramientas de prueba paga rápidamente.

Mocha todavía tiene sentido en servicios de Node.js más antiguos o en códigobases largas de vida donde el ecosistema alrededor de ella ya está asentado. Pero para un ingeniero de nivel medio que está configurando un conjunto robusto desde cero, Jest suele eliminar más fricciones de las que crea.

Una nota importante de alcance. Cypress y Playwright son herramientas excelentes, pero resuelven un problema diferente. Son mejores para las pruebas de nivel de navegador y de final a final, no para el rápido bucle interior donde las pruebas unitarias del trabajo de JavaScript deberían vivir.

Configuración del Proyecto y Tu Primer Test

Un conjunto de pruebas limpio debería ser aburrido. Si agregar el primer test siente complicado, el conjunto probablemente no se mantendrá saludable.

Un hombre con gafas trabajando en un proyecto de programación en una laptop en una mesa de madera.

Una configuración de Jest simple

Comienza con un proyecto de JavaScript que ya tiene un package.jsonLuego agrega Jest como una dependencia de desarrollo y configura un script de prueba.

{
  "scripts": {
    "test": "jest"
  }
}

Es suficiente para muchos proyectos. Puedes agregar más configuración más adelante si tu sistema de módulos, tu transpilación o tu estructura de monorepo requieren.

Si estás construyendo una aplicación Capacitor localmente y quieres que tu entorno de desarrollo esté en orden antes de agregar pruebas alrededor de la lógica compartida, Capgo's guía para configurando un entorno local Capacitor es una compañera práctica.

Escriba la prueba antes de la code

El patrón de la prueba primero no es solo una preferencia personal. La guía de JavaScript de la Oficina de Protección Financiera del Consumidor de los EE. UU. recomienda explícitamente escribir la prueba primero, organizar las pruebas con describe y it, y formar comprobaciones alrededor de expect(...) afirmaciones en su guía de pruebas unitarias de JavaScript.

Importa porque la prueba primero cambia cómo diseña code. Las funciones tienden a volverse más pequeñas, las dependencias se vuelven más visibles y los efectos laterales dejan de filtrarse en la lógica que debe permanecer pura.

Aquí hay un ejemplo mínimo:

// math.js
function addTax(amount, rate) {
  return amount + amount * rate;
}

module.exports = { addTax };
// math.test.js
const { addTax } = require('./math');

describe('addTax', () => {
  it('returns the amount with the tax applied', () => {
    expect(addTax(100, 0.2)).toBe(120);
  });
});

Use Arregle Acto Asegura cada vez

El El patrón Arrange, Act, Assert mantiene las pruebas legibles, incluso cuando crecen más complejas. Mantiene las pruebas legibles, incluso cuando crecen más complejas.

  1. Arregle Arregle la entrada y cualquier configuración necesaria.
  2. Actúe Llame a la función.
  3. Asegúrese Asegúrese del resultado.

Aplicado a un ayudante de validación:

function isSupportedPlatform(platform) {
  return ['ios', 'android', 'web', 'desktop'].includes(platform);
}

describe('isSupportedPlatform', () => {
  it('returns true for ios', () => {
    // Arrange
    const platform = 'ios';

    // Act
    const result = isSupportedPlatform(platform);

    // Assert
    expect(result).toBe(true);
  });
});

Las pruebas pequeñas envejecen bien. Una prueba debe responder normalmente a una pregunta, no narrar un flujo de trabajo completo.

Para proyectos de Capacitor y Electron, esa disciplina importa más porque su lógica pura a menudo se encuentra junto a la integración nativa o de escritorio code. Mantenga la regla de negocio probable sin el tiempo de ejecución de la plataforma, y su primera prueba no será la última útil.

Domina los Mocks y la Asincronía Code

La mayoría de los errores en la aplicación code no provienen de sumar dos números. Proviene de code que se sale de sí mismo: solicitudes de red, archivos, APIs de plugins, temporizadores, canales de IPC, capas de almacenamiento.

Es allí donde los Mocks ayudan. Te da control sobre la frontera para que la prueba pueda centrarse en la toma de decisiones de tu code.

Un diagrama de pizarra que ilustra una arquitectura de microservicios con APIs, almacenes de datos, servicios externos y flujo de datos impulsado por eventos.

Mockea las fronteras, no todo

La guía de pruebas mantenibles enfatiza cobertura de un comportamiento único y una sola afirmación fuerte por prueba, y también advierte que el uso excesivo de Mocks hace que las pruebas sean frágiles y estrechamente acopladas a detalles de implementación, como se resume en este artículo de TestRail sobre pruebas unitarias mantenibles.

Y eso importa mucho en JavaScript. Los equipos a menudo comienzan por mockear cada módulo importado y terminan probando si las funciones llaman a otras funciones en el 'orden correcto' en lugar de probar el comportamiento real.

Objetivo equivocado para una prueba con mucho mock:

  • si el ayudante A llamó al ayudante B
  • si el servicio C llamó al serializador D
  • si una función interna privada se ejecutó dos veces

Objetivo mejor:

  • qué devolvió la función
  • si manejo correctamente una dependencia fallida
  • si transformó los datos en la forma esperada

Un patrón mejor para Capacitor y Electron code

En aplicaciones móviles y de escritorio, prefiero una capa de envoltura alrededor de las API nativas o de plataforma. Luego, las pruebas unitarias simulan la capa, no la plataforma en sí.

Estructura de ejemplo:

// cameraGateway.js
async function getPhoto(cameraPlugin) {
  return cameraPlugin.getPhoto();
}

module.exports = { getPhoto };
// profilePhotoService.js
async function loadProfilePhoto(cameraGateway) {
  const photo = await cameraGateway.getPhoto();
  return { path: photo.path, ready: true };
}

module.exports = { loadProfilePhoto };
// profilePhotoService.test.js
const { loadProfilePhoto } = require('./profilePhotoService');

test('returns mapped photo data', async () => {
  const fakeCameraGateway = {
    getPhoto: jest.fn().mockResolvedValue({ path: '/tmp/pic.jpg' })
  };

  const result = await loadProfilePhoto(fakeCameraGateway);

  expect(result).toEqual({ path: '/tmp/pic.jpg', ready: true });
});

Ese patrón funciona también para Electron. Envuelve ipcRendererAcceso a archivos, o integraciones de shell detrás de un adaptador delgado. Los tests unitarios golpean la capa de servicio, no la capa de tiempo directamente.

Para equipos que están probando la lógica de lanzamiento y los caminos de actualización en aplicaciones Capacitor, Capgo tiene una guía relevante sobre la prueba de actualizaciones OTA de Capacitor con escenarios de simulación.

Un walkthrough rápido ayuda si su equipo todavía está normalizando el estilo de prueba asíncrono:

Prueba de flujos asíncronos sin flaqueza

Usa async/await en los tests cuando la code bajo prueba devuelve una promesa. Es más claro que los patrones repletos de callbacks y es más fácil de depurar.

async function fetchProfile(api) {
  const response = await api.getUser();
  return response.name;
}

test('returns the user name from the API response', async () => {
  const api = {
    getUser: jest.fn().mockResolvedValue({ name: 'Ava' })
  };

  const result = await fetchProfile(api);

  expect(result).toBe('Ava');
});

También prueba el camino de falla:

test('throws when the API request fails', async () => {
  const api = {
    getUser: jest.fn().mockRejectedValue(new Error('network failed'))
  };

  await expect(fetchProfile(api)).rejects.toThrow('network failed');
});

Prueba tanto el camino feliz como el camino feo. En producción, el camino feo es el que los usuarios recuerdan.

Estrategias Avanzadas para Pruebas Robustas

Un conjunto de pruebas se vuelve útil cuando sigue siendo útil después de que code cambia. Eso es más difícil que escribir una pila de tests que pasan.

Un diagrama que ilustra estrategias para construir software robusto a través de una cobertura de prueba integral y conjuntos de pruebas mantenibles.

Use the testing split as a budget

Una guía práctica recomienda una 70/20/10 dividido en pruebas unitarias, de integración y de fin de ciclo, con pruebas unitarias que proporcionan la retroalimentación más rápida y las fallas más estables. La misma guía dice que una suite de pruebas unitarias completa debería terminar en menos de 10 segundos, y las comprobaciones pre-commit deberían mantenerse en menos de 5 segundos, según esta guía de pruebas de OpenReplay.

Trato eso como una herramienta de presupuestación, no como una religión. Si la mayor parte de su esfuerzo se dirige a pruebas de fin de ciclo, su equipo esperará demasiado tiempo para obtener retroalimentación. Si todo es solo unitario, se perderán las verdaderas fronteras del sistema.

Para una aplicación Capacitor o Electron, un equilibrio saludable suele verse así:

  • Pruebas unitarias para la lógica de precios, reglas de permisos, serialización, elegibilidad de actualización, banderas de características y transformaciones de estado
  • Pruebas de integración para adaptadores de almacenamiento, envolturas de plugins y contratos de IPC
  • Pruebas E2E para un par de viajes críticos como inicio de sesión, flujo de compra, sincronización o promt de actualización

La cobertura es una linterna, no un objetivo

Los informes de cobertura son útiles cuando ayudan a detectar ramas no probadas en lógica importante. Se vuelven perjudiciales cuando los equipos persiguen porcentajes de cobertura por su propio interés.

Un validador de inicio de sesión con pruebas de casos de borde pensadas aporta más valor que un archivo cubierto lleno de afirmaciones triviales. Eso es especialmente cierto para la entrada pesada code como formularios, parseadores, lógica de fechas y verificaciones de permisos. Si su equipo está ajustando la calidad alrededor de la validación pesada de la interfaz de usuario, esta guía sobre dominio de la validación de formularios en la interfaz de usuario es una buena complementación a la estrategia de pruebas a nivel de unidad.

Las pruebas de comportamiento sobreviven a los refactores

A un conjunto confiable debería permitir que refactores internos sin volver a escribir la mitad de las pruebas. La forma más sencilla de llegar allí es a través de la afirmación comportamiento observable en lugar de detalles de implementación.

Uso de casos que se sostienen bien:

  • Límites de condición como entrada vacía, valores nulos, tipos inválidos y cadenas de texto muy grandes
  • Resultados del dominio como “se rechazan devoluciones por falta de permiso”
  • Transiciones de estado como “marca la actualización como pendiente después de validar el metadato de descarga”

Uso de casos que a menudo se descompone:

  • inspeccionar llamadas de ayuda internas
  • afirmar la secuencia de métodos privados
  • simulando cada capa en la cadena de llamadas

Para equipos de aplicaciones que están construyendo procesos de liberación disciplinados, el artículo de Capgo sobre la garantía de calidad de aplicaciones es útil porque conecta el trabajo de pruebas con la pipelina de liberación más amplia.

Pruebas para CI, Capacitor, y aplicaciones de Electron

Un test que solo se ejecuta en la máquina de un desarrollador no es un seguro. Es un hábito local.

La CI convierte las pruebas unitarias del trabajo de JavaScript en infraestructura de equipo. Cada empuje, solicitud de revisión o rama de liberación puede ejercer los mismos comandos con las mismas expectativas. Esa consistencia importa aún más para los proyectos de Capacitor y Electron, donde el desplazamiento del entorno causa fallas sutiles.

Haga que la CI sea el camino de ejecución por defecto

Al menos, su CI debe instalar dependencias y ejecutar el conjunto de pruebas unitarias en cada conjunto de cambios. Mantenga el comando idéntico a la ejecución local cuando sea posible.

Un flujo de trabajo básico de GitHub Actions puede ser tan pequeño como este:

name: test

on: [push, pull_request]

jobs:
  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test

Eso es suficiente para capturar importaciones rotas, afirmaciones fallidas y suposiciones de plataforma accidentales antes de que lleguen a main.

For equipos móviles que envían a través de pipelines automatizados, Capgo tiene una guía práctica para Configuración de CI/CD para aplicaciones Capacitor.

Pruebas de interacción de plugins Capacitor

La forma incorrecta de probar unidades de Capacitor code es tirar plugins nativos directamente a cada servicio. Eso acopla su conjunto de pruebas a la puente de plataforma.

El patrón mejor es una abstracción delgada:

// deviceStorage.js
async function saveFile(filesystem, path, data) {
  return filesystem.writeFile({ path, data });
}

module.exports = { saveFile };
// draftService.js
async function persistDraft(storage, draft) {
  await storage.save('draft.json', JSON.stringify(draft));
  return { saved: true };
}

module.exports = { persistDraft };
// draftService.test.js
const { persistDraft } = require('./draftService');

test('persists a serialized draft', async () => {
  const storage = {
    save: jest.fn().mockResolvedValue(undefined)
  };

  const result = await persistDraft(storage, { title: 'Hello' });

  expect(result).toEqual({ saved: true });
});

La misma idea se aplica a la acceso a la cámara, promps de biométrica, registro de tokens de notificación y estado de red. Mantenga las llamadas de plugins en adaptadores. Pruebe la lógica de la aplicación contra interfaces que controla.

Pruebas de IPC y main renderer de Electron code

Las aplicaciones de Electron tienen dos importantes juntas: proceso principal code y proceso de renderizado codeNo borre las juntas en las pruebas.

Una configuración confiable suele separar:

  • Pruebas de unidades del unidad de renderizado para modelos de vista, estado, formateo y lógica de negocio en la interfaz de usuario
  • Pruebas de unidades del proceso principal para menús, operaciones de archivo y decisiones de ciclo de vida de la aplicación
  • Pruebas del contrato de IPC para la forma de los mensajes y las respuestas esperadas

Ejemplo de wrapper de IPC:

// ipcGateway.js
function sendSettings(ipcRenderer, payload) {
  ipcRenderer.send('settings:update', payload);
}

module.exports = { sendSettings };
// ipcGateway.test.js
const { sendSettings } = require('./ipcGateway');

test('sends settings update over ipc', () => {
  const ipcRenderer = { send: jest.fn() };

  sendSettings(ipcRenderer, { theme: 'dark' });

  expect(ipcRenderer.send).toHaveBeenCalledWith('settings:update', { theme: 'dark' });
});

Si cambias más tarde la implementación interna de un helper a otro, esta prueba sigue siendo válida porque verifica el comportamiento que importa. Ese es el estándar que deseas en escritorio y móvil code.

Preguntas Frecuentes sobre Pruebas de Unidades de JavaScript

¿Cuál es la diferencia entre pruebas de unidades, integración y E2E

A unit test verifica una pequeña pieza de lógica de manera aislada. Un integration test verifica si un par de componentes o servicios funcionan correctamente. Un end-to-end test ejercita un recorrido del usuario a través de la aplicación en ejecución.

Utilice las pruebas unitarias para obtener confianza rápida en las reglas comerciales. Utilice las pruebas de integración para junturas como almacenamiento, envolturas de plugins y IPC. Utilice las pruebas E2E con moderación para los flujos de trabajo que serían muy perjudiciales si se rompieran.

¿Debemos aspirar a una cobertura completa

No. La cobertura completa puede empujar a los equipos hacia pruebas de baja valor.

La cobertura es útil cuando revela riesgos code que nadie ha ejercitado. No es útil cuando los ingenieros agregan afirmaciones superficiales solo para satisfacer una pantalla de control. Si su conjunto de pruebas es frágil, más cobertura no lo salvará.

¿Cómo agregamos pruebas a un código existente

Comience donde ya ocurren cambios. No congele al equipo y anuncie una gran reescritura de la estrategia de pruebas.

Una secuencia práctica se parece a esto:

  • Protege primero los code activos agregando pruebas a los módulos que tocas durante el trabajo de características o correcciones de errores
  • Extrae lógica pura de archivos difíciles de probar para que las reglas comerciales puedan ser probadas sin ruido de marco o tiempo de ejecución
  • Agrega envolturas de costura alrededor de plugins nativos, clientes de red, llamadas al sistema de archivos y IPC de Electron
  • Rechaza patrones frágiles cuando se introducen mocks. La guía de prácticas de prueba de JavaScript es especialmente útil aquí porque destaca el problema a menudo pasado por alto de sobre-mockeo y las pruebas frágiles que siguen

El objetivo no es la completitud inmediata. Es una mejora constante en los lugares donde las regresiones cuestan más al equipo.


Si su equipo envía aplicaciones Capacitor o aplicaciones de Electron y necesita un proceso de liberación más limpio alrededor de los cambios de JavaScript, Capgo es una opción a considerar. Proporciona actualizaciones en vivo para aplicaciones de CapacitorJS y Electron, con controles de lanzamiento y observabilidad, por lo que los equipos pueden combinar pruebas unitarias sólidas con un camino más seguro para enviar cambios en el paquete web sin tener que esperar a la revisión de la tienda para cada corrección.

Actualizaciones en vivo para aplicaciones Capacitor

Cuando un error en la capa web está en vivo, envíe la corrección a través de Capgo en lugar de esperar días para la aprobación de la tienda de aplicaciones. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen en el camino de revisión normal.

Iniciar Ahora

Últimas noticias de nuestro Blog

Capgo le da las mejores pistas que necesita para crear una aplicación móvil verdaderamente profesional.