4. Qué significa integrar componentes de software

4.1 Introducción

Integrar componentes de software significa hacer que partes separadas de un sistema colaboren para lograr un comportamiento común. Una aplicación real rara vez está formada por una sola pieza: normalmente contiene módulos, capas, servicios, bases de datos, archivos, APIs, procesos en segundo plano y configuraciones.

Cada componente puede tener una responsabilidad propia, pero el valor para el usuario aparece cuando esas responsabilidades se combinan correctamente. Por ejemplo, registrar una compra puede requerir validación, cálculo, persistencia, actualización de stock y envío de notificaciones.

Las pruebas de integración existen porque entre esas partes aparecen acuerdos, dependencias y riesgos que no siempre se observan al probar unidades aisladas.

4.2 Qué es un componente

En este curso usaremos la palabra componente en un sentido amplio. Un componente es una parte del sistema que cumple una responsabilidad y puede interactuar con otras partes.

Según el tipo de aplicación, un componente puede ser:

  • Una clase o módulo.
  • Una capa de la aplicación, como controlador, servicio o repositorio.
  • Un servicio interno.
  • Una base de datos.
  • Una API externa.
  • Una cola de mensajes.
  • Un proceso programado.
  • Un sistema de archivos o almacenamiento externo.

Lo importante no es el tamaño exacto del componente, sino que tenga una responsabilidad identificable y una forma de colaborar con otros.

4.3 Integrar no es solo conectar

Una idea limitada sería pensar que integrar significa simplemente hacer que dos partes “se llamen”. En realidad, integrar implica mucho más.

Cuando dos componentes se integran, deben coincidir en varios aspectos:

  • Cómo se invocan.
  • Qué datos intercambian.
  • Qué formatos usan.
  • Qué errores pueden devolver.
  • Qué tiempos de respuesta se consideran aceptables.
  • Qué estado comparten o modifican.
  • Qué responsabilidad tiene cada parte.
Integrar componentes significa lograr que sus responsabilidades separadas funcionen como una colaboración coherente.

4.4 Interfaces entre componentes

La integración ocurre a través de una interfaz. Una interfaz es el punto de contacto entre componentes. Puede ser una función pública, un método, una ruta HTTP, una consulta, una tabla, un archivo, un mensaje o cualquier mecanismo usado para intercambiar información.

Por ejemplo:

  • Un controlador expone una ruta para crear usuarios.
  • Un servicio ofrece un método para calcular una factura.
  • Un repositorio expone una operación para guardar una entidad.
  • Una API recibe una solicitud JSON y devuelve una respuesta.
  • Una cola acepta mensajes con determinada estructura.

Muchas fallas de integración aparecen cuando una interfaz cambia, está mal documentada o se usa con datos que no respeta.

4.5 Contratos y expectativas

Detrás de una interfaz existe un contrato. El contrato define qué espera una parte y qué promete la otra. Puede estar escrito en documentación formal o simplemente expresado en el código y en los casos de uso.

Un contrato puede incluir:

  • Parámetros obligatorios y opcionales.
  • Tipos de datos.
  • Formato de fechas, importes o identificadores.
  • Códigos de estado.
  • Estructura de una respuesta.
  • Errores esperados.
  • Reglas sobre valores permitidos.

Integrar correctamente significa respetar estas expectativas. Si un componente envía “fechaAlta” y otro espera “fecha_alta”, la lógica interna puede estar bien, pero la integración fallará.

4.6 Dependencias entre componentes

Un componente depende de otro cuando necesita su colaboración para completar una tarea. Las dependencias pueden ser internas o externas.

Tipo de dependencia Ejemplo Riesgo posible
Interna Un servicio usa un repositorio para guardar datos. La consulta no coincide con el esquema real.
Externa La aplicación consulta un proveedor de pagos. El proveedor cambia el formato de respuesta.
Infraestructura Un proceso publica mensajes en una cola. La cola no existe en el ambiente de pruebas.
Datos compartidos Dos módulos leen y escriben la misma tabla. Un módulo deja datos en un estado que el otro no espera.

Las pruebas de integración ayudan a descubrir si esas dependencias están disponibles, configuradas y usadas correctamente.

4.7 Integración entre capas

Muchas aplicaciones se organizan en capas. Una estructura común incluye controlador, servicio y repositorio. Cada capa tiene una responsabilidad distinta:

  • Controlador: recibe una solicitud y prepara una respuesta.
  • Servicio: aplica reglas de negocio y coordina operaciones.
  • Repositorio: accede a la base de datos u otro almacenamiento.

Integrar estas capas significa verificar que la solicitud pase correctamente de una capa a otra, que los datos se transformen como corresponde y que el resultado final sea coherente.

Por ejemplo, si el controlador recibe un pedido para crear un cliente, el servicio debe validar las reglas necesarias y el repositorio debe guardar el cliente con los valores esperados.

4.8 Integración entre servicios

En sistemas más distribuidos, distintos servicios pueden colaborar entre sí. Un servicio de ventas puede consultar un servicio de usuarios, un servicio de stock y un servicio de pagos.

La integración entre servicios agrega riesgos como:

  • Errores de red.
  • Versiones incompatibles.
  • Respuestas lentas.
  • Datos incompletos.
  • Distintas formas de representar el mismo concepto.
  • Errores de autenticación o autorización entre servicios.

En estos casos, probar la integración no consiste solo en llamar al servicio. También hay que revisar qué ocurre cuando la comunicación falla o cuando la respuesta no es la esperada.

4.9 Integración mediante datos compartidos

A veces los componentes no se comunican directamente, sino a través de datos compartidos. Por ejemplo, un proceso guarda registros en una tabla y otro proceso los lee más tarde para generar reportes.

Este tipo de integración requiere prestar atención a:

  • Estructura de tablas o archivos.
  • Estados permitidos.
  • Campos obligatorios.
  • Orden de procesamiento.
  • Consistencia entre lectura y escritura.
  • Limpieza de datos de prueba.

Un error común es que un componente guarde datos válidos para sí mismo, pero insuficientes o ambiguos para el componente que debe consumirlos después.

4.10 Integración síncrona y asíncrona

Una integración puede ser síncrona o asíncrona.

Tipo Qué significa Ejemplo
Síncrona Un componente espera una respuesta inmediata de otro. Consultar una API para validar un pago.
Asíncrona Un componente deja un mensaje o evento para que otro lo procese luego. Publicar un evento para enviar un correo de confirmación.

Las integraciones asíncronas suelen requerir cuidados adicionales en las pruebas, porque el resultado puede no aparecer de inmediato. En esos casos, se debe verificar que el mensaje se publique, que el consumidor lo procese y que el estado final sea el esperado.

4.11 Estado compartido

Muchos componentes trabajan sobre un estado compartido. Ese estado puede estar en una base de datos, memoria, archivos, caché o cola de mensajes. Integrar componentes implica asegurarse de que ese estado se mantenga consistente.

Por ejemplo, si una compra se confirma, no debería quedar una orden como pagada y el stock sin descontar. Si una operación falla, tampoco debería dejar datos intermedios que luego generen errores.

Las pruebas de integración deben observar no solo la respuesta inmediata, sino también el estado que queda después de ejecutar la operación.

4.12 Límites entre componentes

Para probar integraciones, necesitamos reconocer dónde termina un componente y dónde empieza otro. Ese límite puede estar definido por una clase, una capa, un servicio, una API, una tabla, un archivo o una cola.

Identificar límites permite decidir:

  • Qué partes serán reales en la prueba.
  • Qué dependencias se simularán.
  • Qué datos se deben preparar.
  • Qué resultado se debe observar.
  • Dónde puede estar la causa si la prueba falla.

Un límite claro ayuda a que la prueba tenga un objetivo claro. Si no sabemos qué estamos integrando, tampoco sabremos interpretar bien el resultado.

4.13 Ejemplo completo de integración

Supongamos una aplicación que permite registrar una reserva de hotel. Para completar la operación pueden colaborar varios componentes:

  • El controlador recibe fecha, habitación y datos del cliente.
  • El servicio de reservas valida disponibilidad.
  • El repositorio consulta habitaciones ocupadas.
  • La base de datos guarda la nueva reserva.
  • El servicio de pagos registra una seña.
  • El servicio de notificaciones envía la confirmación.

Una prueba de integración podría enfocarse solo en controlador, servicio, repositorio y base de datos. Otra podría incluir también el servicio de pagos, o reemplazarlo por una simulación controlada. La decisión depende del objetivo de la prueba.

4.14 Señales de una integración riesgosa

No todas las integraciones tienen el mismo riesgo. Algunas merecen más atención porque concentran más posibilidades de falla.

Conviene priorizar integraciones donde:

  • Intervienen datos críticos del negocio.
  • Hay servicios externos o infraestructura compartida.
  • Existen formatos complejos o poco documentados.
  • Varias funcionalidades dependen del mismo componente.
  • Una falla puede generar pérdida de datos, dinero o confianza.
  • El componente cambió recientemente.

4.15 Qué debes recordar de este tema

  • Integrar componentes significa hacer que partes separadas colaboren correctamente.
  • La integración ocurre a través de interfaces y contratos.
  • Una dependencia puede ser interna, externa, de infraestructura o de datos compartidos.
  • Integrar no es solo conectar: también implica datos, formatos, errores, tiempos y estado.
  • Reconocer límites entre componentes ayuda a diseñar pruebas de integración más claras.
  • Las integraciones más riesgosas deben priorizarse en la estrategia de pruebas.

4.16 Conclusión

Integrar componentes de software es lograr que responsabilidades separadas se combinen de forma correcta y predecible. Allí aparecen acuerdos entre partes, dependencias, datos compartidos, configuraciones y posibles fallas de coordinación.

Las pruebas de integración ayudan a comprobar que esos acuerdos se cumplan y que el sistema mantenga un comportamiento coherente cuando sus componentes trabajan juntos.

En el próximo tema estudiaremos los errores típicos que aparecen al integrar módulos, para reconocerlos con mayor rapidez y diseñar pruebas que los detecten.