Guía de Pruebas
Guía de Pruebas
Sección titulada «Guía de Pruebas»Aprende a probar tus aplicaciones Veloce-TS de manera efectiva.
Tabla de Contenidos
Sección titulada «Tabla de Contenidos»- Introducción
- Utilidades de Prueba
- Pruebas Unitarias
- Pruebas de Integración
- Pruebas con Dependencias
- Mejores Prácticas
Introducción
Sección titulada «Introducción»Veloce proporciona utilidades de prueba para facilitar el testing de tus aplicaciones. El framework usa el test runner integrado de Bun, que es rápido y tiene una API compatible con Jest.
Configuración
Sección titulada «Configuración»# Las pruebas se ejecutan con Bunbun test
# Modo watchbun test --watch
# Coberturabun test --coverageUtilidades de Prueba
Sección titulada «Utilidades de Prueba»createTestApp()
Sección titulada «createTestApp()»Crea una instancia de prueba de tu aplicación.
import { createTestApp } from 'veloce-ts/testing';
const app = createTestApp();TestClient
Sección titulada «TestClient»Cliente HTTP para hacer peticiones de prueba.
import { TestClient } from 'veloce-ts/testing';
const client = new TestClient(app);
// Hacer peticionesconst response = await client.get('/users');const data = await response.json();mockDependency()
Sección titulada «mockDependency()»Simula una dependencia en el contenedor DI.
import { mockDependency } from 'veloce-ts/testing';
const mockDb = { getUsers: async () => [{ id: 1, name: 'Prueba' }],};
mockDependency(DatabaseService, mockDb);Pruebas Unitarias
Sección titulada «Pruebas Unitarias»Probando Controladores
Sección titulada «Probando Controladores»import { describe, it, expect, beforeEach } from 'bun:test';import { createTestApp, TestClient } from 'veloce-ts/testing';import { UserController } from './controllers/user.controller';
describe('UserController', () => { let app: Veloce; let client: TestClient;
beforeEach(() => { app = createTestApp(); app.include(UserController); client = new TestClient(app); });
it('debería obtener todos los usuarios', async () => { const response = await client.get('/users');
expect(response.status).toBe(200);
const data = await response.json(); expect(data).toBeArray(); });
it('debería crear usuario', async () => { const userData = { name: 'John Doe', email: 'john@example.com', };
const response = await client.post('/users', userData);
expect(response.status).toBe(201);
const data = await response.json(); expect(data.name).toBe(userData.name); });
it('debería validar datos de usuario', async () => { const invalidData = { name: 'J', // Muy corto email: 'email-invalido', };
const response = await client.post('/users', invalidData);
expect(response.status).toBe(422); });});Probando Servicios
Sección titulada «Probando Servicios»import { describe, it, expect } from 'bun:test';import { UserService } from './services/user.service';
describe('UserService', () => { it('debería obtener usuarios', async () => { const service = new UserService(); const users = await service.getUsers();
expect(users).toBeArray(); });
it('debería encontrar usuario por id', async () => { const service = new UserService(); const user = await service.getUserById('1');
expect(user).toBeDefined(); expect(user?.id).toBe('1'); });});Pruebas de Integración
Sección titulada «Pruebas de Integración»Probando Aplicación Completa
Sección titulada «Probando Aplicación Completa»import { describe, it, expect, beforeAll, afterAll } from 'bun:test';import { Veloce } from 'veloce-ts';import { UserController } from './controllers/user.controller';import { DatabaseService } from './services/database.service';
describe('Pruebas de Integración', () => { let app: Veloce; let server: any;
beforeAll(async () => { app = new Veloce();
// Configurar base de datos const db = new DatabaseService(); await db.connect();
app.getContainer().register(DatabaseService, { scope: 'singleton', factory: () => db, });
app.include(UserController);
server = app.listen(3001); });
afterAll(async () => { server.close(); });
it('debería crear y recuperar usuario', async () => { // Crear usuario const createResponse = await fetch('http://localhost:3001/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Usuario de Prueba', email: 'test@example.com', }), });
expect(createResponse.status).toBe(201); const createdUser = await createResponse.json();
// Recuperar usuario const getResponse = await fetch(`http://localhost:3001/users/${createdUser.id}`); expect(getResponse.status).toBe(200);
const retrievedUser = await getResponse.json(); expect(retrievedUser.id).toBe(createdUser.id); });});Pruebas con Dependencias
Sección titulada «Pruebas con Dependencias»Simulando Dependencias
Sección titulada «Simulando Dependencias»import { describe, it, expect, beforeEach } from 'bun:test';import { createTestApp, mockDependency, TestClient } from 'veloce-ts/testing';
describe('UserController con Mocks', () => { let app: Veloce; let client: TestClient; let mockDb: any;
beforeEach(() => { app = createTestApp();
// Crear mock mockDb = { getUsers: async () => [ { id: 1, name: 'Usuario Mock 1' }, { id: 2, name: 'Usuario Mock 2' }, ], };
// Reemplazar servicio real con mock mockDependency(DatabaseService, mockDb);
app.include(UserController); client = new TestClient(app); });
it('debería usar base de datos simulada', async () => { const response = await client.get('/users'); const data = await response.json();
expect(data).toHaveLength(2); expect(data[0].name).toBe('Usuario Mock 1'); });});Mejores Prácticas
Sección titulada «Mejores Prácticas»1. Usa Nombres de Prueba Descriptivos
Sección titulada «1. Usa Nombres de Prueba Descriptivos»// ✓ Buenoit('debería retornar 404 cuando el usuario no existe', async () => {});
// ✗ Maloit('prueba usuario', async () => {});2. Patrón Arrange-Act-Assert
Sección titulada «2. Patrón Arrange-Act-Assert»it('debería crear usuario', async () => { // Arrange (Preparar) const userData = { name: 'John Doe', email: 'john@example.com', };
// Act (Actuar) const response = await client.post('/users', userData); const data = await response.json();
// Assert (Afirmar) expect(response.status).toBe(201); expect(data.name).toBe(userData.name);});3. Prueba Casos Límite
Sección titulada «3. Prueba Casos Límite»describe('UserController', () => { it('debería manejar lista vacía', async () => { // Probar cuando no existen usuarios });
it('debería manejar formato de ID inválido', async () => { // Probar con ID no numérico });
it('debería manejar campos requeridos faltantes', async () => { // Probar validación });});4. Limpia Después de las Pruebas
Sección titulada «4. Limpia Después de las Pruebas»describe('UserController', () => { let db: DatabaseService;
beforeEach(async () => { db = new InMemoryDatabaseService(); await db.connect(); });
afterEach(async () => { await db.clear(); await db.disconnect(); });});Ejecutando Pruebas
Sección titulada «Ejecutando Pruebas»Ejecutar Todas las Pruebas
Sección titulada «Ejecutar Todas las Pruebas»bun testEjecutar Archivo de Prueba Específico
Sección titulada «Ejecutar Archivo de Prueba Específico»bun test user.test.tsModo Watch
Sección titulada «Modo Watch»bun test --watchCobertura
Sección titulada «Cobertura»bun test --coveragePróximos Pasos
Sección titulada «Próximos Pasos»- Revisa la Guía de Inicio
- Aprende sobre Inyección de Dependencias
- Lee la Referencia API