TL;DR
- Mocha provee estructura de tests (
describe,it) — trae tu propia librería de assertions- Combina con Chai para assertions legibles:
expect(value).to.equal(expected)- Hooks:
before,after,beforeEach,afterEachpara setup/teardown- Soporte async: callbacks (
done), promises, async/await — todo funciona- Flexible y modular — elige tus herramientas
Ideal para: Proyectos Node.js, equipos que quieren elegir librería de assertions Omite si: Prefieres soluciones todo-en-uno (usa Jest) Tiempo de lectura: 14 minutos
Tu proyecto Node.js necesita tests. Jest se siente pesado para un servicio pequeño. Quieres elegir tu propio estilo de assertions. Necesitas algo que funcione con tus herramientas existentes.
Mocha no estorba. Ejecuta tests, provee hooks, maneja async — nada más. Tú eliges la librería de assertions, herramienta de mocking y reporter.
¿Qué es Mocha?
Mocha es un framework de testing JavaScript para Node.js y navegadores. Provee estructura para organizar tests pero intencionalmente deja assertions y mocking a otras librerías.
Por qué Mocha:
- Flexible — funciona con cualquier librería de assertions
- Async-friendly — callbacks, promises, async/await
- Ecosistema rico — muchos reporters y plugins
- Soporte browser — mismos tests corren en Node y navegador
Instalación y Setup
npm install mocha chai --save-dev
// package.json
{
"scripts": {
"test": "mocha",
"test:watch": "mocha --watch"
}
}
// .mocharc.json
{
"spec": "test/**/*.test.js",
"timeout": 5000,
"recursive": true
}
Escribiendo Tu Primer Test
// test/calculator.test.js
const { expect } = require('chai');
const Calculator = require('../src/calculator');
describe('Calculator', () => {
describe('add()', () => {
it('debería sumar dos números positivos', () => {
const calc = new Calculator();
expect(calc.add(2, 3)).to.equal(5);
});
it('debería manejar números negativos', () => {
const calc = new Calculator();
expect(calc.add(-1, 1)).to.equal(0);
});
});
});
Chai Assertions
const { expect } = require('chai');
// Igualdad
expect(value).to.equal(5);
expect(value).to.deep.equal({ a: 1 });
// Verificación de tipos
expect('hello').to.be.a('string');
expect([1, 2]).to.be.an('array');
// Comparaciones
expect(10).to.be.above(5);
expect(10).to.be.below(20);
// Strings
expect('hello world').to.include('world');
expect('hello').to.have.lengthOf(5);
// Arrays
expect([1, 2, 3]).to.include(2);
expect([1, 2, 3]).to.have.lengthOf(3);
// Objetos
expect({ a: 1 }).to.have.property('a');
// Errores
expect(() => fn()).to.throw();
expect(() => fn()).to.throw('mensaje de error');
Lifecycle Hooks
describe('User Service', () => {
let db;
before(async () => {
// Una vez antes de todos los tests
db = await connectToDatabase();
});
after(async () => {
// Una vez después de todos los tests
await db.close();
});
beforeEach(() => {
// Antes de cada test
});
afterEach(async () => {
// Después de cada test
await db.collection('users').deleteMany({});
});
it('debería crear usuario', async () => {
// ...
});
});
Testing Async
Async/Await (Recomendado)
it('debería obtener usuario', async () => {
const user = await fetchUser(1);
expect(user.name).to.equal('John');
});
it('debería manejar errores', async () => {
try {
await fetchUser(999);
expect.fail('Debería haber lanzado error');
} catch (err) {
expect(err.message).to.include('not found');
}
});
Timeout
it('debería completar en 5 segundos', async function() {
this.timeout(5000);
await longRunningOperation();
});
Mocking con Sinon
npm install sinon --save-dev
const sinon = require('sinon');
const axios = require('axios');
describe('API Client', () => {
let axiosStub;
beforeEach(() => {
axiosStub = sinon.stub(axios, 'get');
});
afterEach(() => {
axiosStub.restore();
});
it('debería obtener datos', async () => {
axiosStub.resolves({ data: { id: 1, name: 'Test' } });
const result = await apiClient.fetchUser(1);
expect(result.name).to.equal('Test');
});
});
Integración CI/CD
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
Mocha con Asistencia de IA
Lo que la IA hace bien:
- Generar casos de prueba desde firmas de funciones
- Crear variaciones de assertions para edge cases
- Convertir entre estilos de assertions
- Sugerir implementaciones de mock
Lo que necesita humanos:
- Decidir qué testear
- Entender lógica de negocio
- Depurar tests flaky
FAQ
¿Qué es Mocha?
Mocha es un framework de testing JavaScript flexible para Node.js y navegadores. Provee estructura de tests (describe, it), lifecycle hooks (before, after) y soporte async, pero intencionalmente no incluye assertions o mocking. Lo combinas con Chai para assertions y Sinon para mocking.
¿Mocha vs Jest — cuál es mejor?
Jest es todo-en-uno con assertions, mocking y coverage integrados. Mocha es modular — eliges cada componente. Jest es más simple para empezar; Mocha ofrece más flexibilidad. Usa Jest para proyectos React, Mocha cuando quieras estilos específicos de assertions.
¿Qué librería de assertions funciona con Mocha?
Chai es la opción más popular con tres estilos: expect (BDD), should (BDD) y assert (TDD). El módulo assert integrado de Node también funciona. La mayoría de equipos prefieren el estilo expect de Chai por legibilidad.
¿Puede Mocha testear código async?
Sí, excelentemente. Mocha soporta tres patrones async: callbacks (parámetro done), promises (retornar la promise) y async/await (solo usar función async). Mocha maneja todos los patrones nativamente.
Recursos Oficiales
Ver También
- Jest Testing Tutorial - Alternativa todo-en-uno
- Cypress Tutorial - Testing E2E
- WebdriverIO Tutorial - Automatización de navegador con Mocha
- GitHub Actions para QA - Integración CI/CD
