Pruebas en TypeScript: unit, integration, e2e de la A a la Z

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: Por qué las pruebas en TypeScript son un must have

TypeScript es una herramienta poderosa que añade tipado estático a JavaScript. Sin embargo, incluso el sistema de tipos más estricto no garantiza que tu código funcione correctamente en tiempo de ejecución. Errores, fallos lógicos, manejo incorrecto de casos límite — todo esto queda fuera de la compilación. Aquí es donde las pruebas vienen al rescate.

En este artículo analizaremos tres niveles principales de pruebas en TypeScript: unit (unitarias), integration (integración) y e2e (end-to-end). Aprenderás en qué se diferencian, cuándo aplicar cada una y verás ejemplos reales de código. Después de leerlo, podrás configurar un pipeline de pruebas completo para tu proyecto TypeScript.



1. Pruebas unitarias: verificamos unidades atómicas de código

Las pruebas unitarias son el nivel de verificación más rápido y económico. Aíslan una función, método o clase y lo prueban sin dependencias externas (bases de datos, API, sistema de archivos).



1.1 Elección de herramienta y configuración

El framework más popular para TypeScript es Jest. Tiene soporte integrado para TypeScript a través de ts-jest o @swc/jest.

// Instalaciónnpm install --save-dev jest @types/jest ts-jest

// Inicialización de configuraciónnpx ts-jest config:init

Después de esto, aparecerá en la raíz el archivo jest.config.js con la configuración.



1.2 Ejemplo de prueba unitaria para una función

Supongamos que tenemos una función simple para calcular un descuento:

// discount.tsexport function applyDiscount(price: number, discountPercent: number): number {  if (discountPercent < 0 || discountPercent > 100) {    throw new Error('Porcentaje de descuento inválido');  }  return price - (price * discountPercent) / 100;}

Escribamos una prueba unitaria para ella:

// discount.test.tsimport { applyDiscount } from './discount';

describe('applyDiscount', () => { it('debe calcular correctamente un descuento del 10%', () => { expect(applyDiscount(1000, 10)).toBe(900); });

it('debe devolver el precio original con descuento del 0%', () => { expect(applyDiscount(500, 0)).toBe(500); });

it('debe lanzar un error con descuento mayor al 100%', () => { expect(() => applyDiscount(100, 150)).toThrow('Porcentaje de descuento inválido'); });});

Ejecutamos: npx jest. Las tres pruebas deberían pasar en verde.



1.3 Mocks y stubs

Si la función accede a un servicio externo (por ejemplo, una base de datos), lo reemplazamos con un mock:

// userService.test.tsimport { getUser } from './userService';import { db } from './database';

jest.mock('./database'); // Mock automático

test('getUser devuelve un usuario por ID', async () => { (db.findUser as jest.Mock).mockResolvedValue({ id: 1, name: 'Iván' }); const user = await getUser(1); expect(user.name).toBe('Iván');});


2. Pruebas de integración: verificamos la interacción de módulos

Las pruebas de integración verifican cómo diferentes partes del sistema funcionan juntas: controladores, servicios, repositorios, bases de datos. Son más lentas que las pruebas unitarias, pero brindan mayor confianza en la corrección de las conexiones.



2.1 Probando un endpoint de API con Express

Para probar solicitudes HTTP usamos la librería Supertest junto con Jest.

// Instalaciónnpm install --save-dev supertest @types/supertest

Supongamos que tenemos una aplicación Express:

// app.tsimport express from 'express';import { createUser } from './controllers/userController';

export const app = express();app.use(express.json());app.post('/api/users', createUser);

Prueba de integración:

// app.test.tsimport request from 'supertest';import { app } from './                

Blogs

Book Recommendations