Contenido del curso

Pruebas de Servicios y Dependencias

Unit Testing para Componentes con Inyección de Dependencias

Resumen

Probar componentes Angular que reciben servicios inyectados requiere decisiones técnicas claras: ¿integras el servicio real o lo suplantas con un mock? Esta guía de unit testing con inyección de dependencias muestra cómo configurar el entorno con Spectator, cuándo conviene cada enfoque y qué ajustes hacer cuando la IA genera tests poco mantenibles.

La diferencia entre una prueba unitaria y una de integración aparece justo aquí, cuando un componente como HeaderComponent depende de un CartService que maneja signals reactivos para el carrito de compras.

¿Cómo se prueba un componente Angular con servicios inyectados?

El punto de partida es identificar qué dependencias trae el componente. En el caso de HeaderComponent, hay una inyección directa hacia CartService, que controla el carrito, el total y la lógica reactiva con signals [03:15].

Gracias a los standalone components, desde Angular 19 en adelante ya no necesitas declarar standalone: true porque viene activo por defecto. Esto cambia cómo configuras tus pruebas: el componente trae sus propios imports (CommonModule, RouterLink, subcomponentes) sin que tengas que repetirlos en el setup.

Lo único que sí debes inyectar manualmente son los servicios propios. La configuración mínima queda así:

  • Importas el componente con createComponentFactory o createRoutingFactory si usa router.
  • Declaras providers: [CartService] para inyectar el servicio real.
  • Omites cualquier import que el standalone ya resuelve solo.

¿Qué es una prueba de integración en Angular? Es cuando inyectas el servicio real (no un mock) y verificas que componente y servicio funcionen acoplados. Útil si confías en que el servicio ya tiene sus propios unit tests pasando.

¿Cuándo usar el servicio real y cuándo mockearlo?

Inyectar CartService directamente convierte la prueba en una integración liviana. Funciona, pero no es lo más común. Lo habitual es enviar una suplantación o mock para aislar el componente y evitar que un fallo del servicio rompa pruebas que no le corresponden.

El criterio práctico:

  1. Si el servicio es propio y simple, integrarlo puede ser válido.
  2. Si el servicio hace llamadas HTTP o tiene lógica compleja, mockéalo.
  3. Si quieres pruebas verdaderamente unitarias, siempre suplanta las dependencias.

¿Cómo aprovechar Cursor para generar tests de componentes?

Darle el contexto correcto a la IA marca la diferencia. En la sesión [09:40] se le pasa a Cursor el componente, su HTML y el archivo .spec con el setup inicial, pidiéndole que genere las unit tests.

La IA produce pruebas razonables, pero suele inventar su propio mock en lugar de usar utilidades existentes. La solución es indicarle de forma explícita qué helper usar, por ejemplo: please use generateFakeProduct for mocking. Cursor reescribe los mocks y reemplaza las implementaciones donde corresponde.

¿Por qué no debo usar selectores CSS en los tests? Porque las clases de Tailwind o utilidades cambian rápido y rompen tus pruebas. Mejor usa data-test-id y matchers específicos como toHaveText en lugar de contains por CSS.

¿Cómo refactorizar tests con data-test-id y matchers de Spectator?

Cuando la IA generó una prueba que validaba el total del carrito usando un selector de clase y textContent.contains, el resultado fue frágil. El refactor consiste en dos pasos concretos [16:20]:

  • Agregar data-test-id="total" al elemento HTML que muestra el total.
  • Usar byTestId('total') en el test y validar con toHaveText('Total: 200').

Los detalles importan: dos puntos, espacios y formato del string deben coincidir exactamente para que el matcher pase. Este cambio hace la prueba más legible, más estable y desacoplada de la maquetación.

¿Qué conceptos clave debes dominar para testear componentes con dependencias?

Algunos términos y técnicas que aparecen en el flujo y vale la pena tener claros:

  • Inyección de dependencias: mecanismo de Angular para entregar servicios a componentes; en testing decides si inyectas el real o un mock [00:30].
  • Standalone components: por defecto desde Angular 19, traen sus propios imports sin necesidad de declararlos en el test [05:50].
  • createRoutingFactory: factory de Spectator necesario cuando el componente usa routerLink o routerLinkActive [04:10].
  • Signals: API reactiva que CartService usa para el estado del carrito y el total.
  • Mocking vs integración: mockear aísla el componente; integrar valida el acople real entre piezas.
  • byTestId y toHaveText: matchers de Spectator que reemplazan selectores CSS frágiles [17:00].

¿Cómo decidir entre prompts manuales y reglas reutilizables en Cursor?

Cursor permite definir reglas para que ciertos prompts se apliquen automáticamente. Mientras estés explorando, conviene mantener los prompts ligeros y manuales. Cuando ya tengas un patrón estable (por ejemplo, generar unit tests con generateFakeProduct y data-test-ids), conviértelo en regla para no repetirlo en cada componente.

Esto también funciona si usas otro plugin de IA: el principio es el mismo, darle contexto del componente, su HTML y el setup actual del spec.

¿Tú prefieres integrar el servicio real o siempre vas por el mock? Cuéntame en los comentarios cómo manejas las dependencias en tus tests de componentes.