Testing con Firebase Emulator y PostgreSQL

Este documento explica cómo configurar y usar Firebase Emulator junto con PostgreSQL para las pruebas de testing, asegurando que las pruebas no se conecten a producción.

Introducción

Firebase Emulator Suite junto con una base de datos PostgreSQL de testing permite ejecutar pruebas locales sin conexión a los servicios de producción. Esto es esencial para:

  • Aislamiento: Las pruebas no afectan datos de producción

  • Velocidad: Los emuladores son más rápidos que los servicios en la nube

  • Control: Puedes controlar el estado de los datos en cada prueba

  • Costo: No se generan costos por uso de servicios durante las pruebas

  • Seguridad: Base de datos separada para pruebas evita corrupción de datos de producción

Configuración

1. Configurar Firebase Emulator

El archivo firebase.json ya está configurado con los emuladores necesarios:

{
  "emulators": {
    "auth": {
      "port": 9099
    },
    "functions": {
      "port": 5001
    },
    "firestore": {
      "port": 8080
    },
    "hosting": {
      "port": 5000
    },
    "storage": {
      "port": 9199
    },
    "ui": {
      "enabled": true,
      "port": 4000
    }
  }
}

2. Entorno de Testing

Se ha creado src/environments/environment.test.ts que configura Firebase para usar emuladores y PostgreSQL para testing:

export const environment = {
  production: false,
  apiUrl: '/api',
  useEmulators: true,
  firebase: {
    apiKey: "demo-api-key",
    authDomain: "demo-project.firebaseapp.com",
    projectId: "demo-project",
    // ... configuración de emuladores
  },
  emulators: {
    auth: { host: "localhost", port: 9099 },
    functions: { host: "localhost", port: 5001 },
    // ...
  },
  database: {
    // Configuración de PostgreSQL para testing
    host: process.env['DB_TEST_HOST'] || 'localhost',
    port: parseInt(process.env['DB_TEST_PORT'] || '5432', 10),
    database: process.env['DB_TEST_NAME'] || 'unosportclub_test',
    user: process.env['DB_TEST_USER'] || 'unosportclub',
    password: process.env['DB_TEST_PASSWORD'] || '',
    ssl: false
  }
};

3. Configuración de Testing

El archivo src/app/app.config.test.ts está configurado para conectar automáticamente a los emuladores cuando se ejecutan las pruebas.

Uso

Iniciar Emuladores

Antes de ejecutar las pruebas, inicia los emuladores de Firebase:

firebase emulators:start --only auth,functions

O para iniciar todos los emuladores:

firebase emulators:start

La UI de emuladores estará disponible en http://localhost:4000.

Ejecutar Pruebas

IMPORTANTE: Antes de ejecutar las pruebas, asegúrate de:

  1. Tener los emuladores de Firebase corriendo

  2. Tener la base de datos PostgreSQL de testing configurada y migrada

  3. Tener las variables de entorno de testing configuradas

Con los emuladores y la base de datos de testing listos, ejecuta las pruebas normalmente:

npm test

O para un proyecto específico:

ng test unosportclub
ng test panel
ng test trainer
ng test sudo

Las pruebas usarán automáticamente el entorno de testing (environment.test.ts) que se conecta a los emuladores locales.

Verificar Conexión a Emuladores

Puedes verificar que las pruebas están usando los emuladores:

  1. Abre la UI de emuladores en http://localhost:4000

  2. Ejecuta las pruebas

  3. Verifica que aparezcan actividades en la UI de emuladores (autenticaciones, llamadas a functions, etc.)

Scripts Útiles

Scripts para Testing

Los siguientes scripts están disponibles en package.json:

{
  "scripts": {
    "test:emulator": "concurrently \"firebase emulators:start --only auth,functions\" \"wait-on http://localhost:9099 http://localhost:5001 && ng test --watch=false\"",
    "test:emulator:watch": "concurrently \"firebase emulators:start --only auth,functions\" \"wait-on http://localhost:9099 http://localhost:5001 && ng test\"",
    "test:db:setup": "cd functions && DATABASE_URL=postgresql://unosportclub:password@localhost:5432/unosportclub_test npm run db:migrate"
  }
}

Scripts disponibles:

  • npm run test:emulator - Inicia emuladores y ejecuta pruebas una vez

  • npm run test:emulator:watch - Inicia emuladores y ejecuta pruebas en modo watch

  • npm run test:db:setup - Configura la base de datos de testing con migraciones

Nota: Ajusta las credenciales en test:db:setup según tu configuración local.

Buenas Prácticas

1. Limpiar Datos entre Pruebas

En tus pruebas, limpia los datos del emulador entre cada test:

import { getAuth } from '@angular/fire/auth';

beforeEach(async () => {
  // Limpiar usuarios del emulador
  const auth = getAuth();
  // ... lógica de limpieza
});

2. Usar Datos de Prueba Consistentes

Crea usuarios y datos de prueba consistentes para cada suite de pruebas:

const TEST_USER = {
  email: 'test@example.com',
  password: 'test123456'
};

3. Verificar Conexión a Emuladores

Añade verificaciones en tus pruebas para asegurar que estás usando emuladores:

it('should use emulator', () => {
  const auth = getAuth();
  expect(auth._delegate._config?.emulator).toBeDefined();
});

4. Aislar Pruebas

Cada prueba debe ser independiente y no depender del estado de otras pruebas.

Troubleshooting

Error: "Emulator not running"

Si recibes errores indicando que el emulador no está corriendo:

  1. Verifica que los emuladores estén iniciados: firebase emulators:start

  2. Verifica los puertos en firebase.json y environment.test.ts

  3. Verifica que no haya conflictos de puertos

Error: "Already connected to emulator"

Si recibes este error, significa que ya estás conectado. Esto es normal y puede ignorarse.

Las pruebas se conectan a producción

Verifica que:

  1. angular.json tenga la configuración de fileReplacements para testing

  2. environment.test.ts tenga useEmulators: true

  3. Los emuladores estén corriendo antes de ejecutar las pruebas