Contenido del curso

Pruebas de Servicios y Dependencias

Cómo espiar Outputs con jest.spyOn en Angular

Resumen

Espiar funciones en unit tests es una de las técnicas más útiles cuando quieres saber si un método se ejecutó, cuántas veces y con qué parámetros. Aquí aprenderás a crear spies manuales en componentes Angular usando Jest y Spectator, además de probar interacciones reales como un clic de usuario.

Qué es un spy en unit testing y para qué sirve

Un spy es un mecanismo que te permite trackear la ejecución de una función: si fue llamada, cuántas veces y con qué argumentos. En el minuto [0:15] se introduce esta idea aplicada al mundo de Jest, donde ya habíamos visto un caso previo con el MetaTagService y jest.fn() para suplantar dependencias.

La diferencia clave aparece cuando lo que quieres espiar no viene por inyección de dependencias. Ahí necesitas otra estrategia.

¿Qué es un spy en Jest? Es una función que envuelve a otra para registrar cada vez que se ejecuta. Te dice si fue llamada, con qué parámetros y cuántas veces, sin alterar su comportamiento original.

Cómo espiar un Output de Angular cuando no es inyección de dependencias

El componente del ejemplo expone un @Output() que emite el producto cada vez que se ejecuta addToCart. Como un output no se registra en providers, el truco es crear el spy directamente sobre el método emit del EventEmitter.

La convención de naming es nombrar la variable como la función a espiar más el sufijo Spy:

typescript const emitSpy = jest.spyOn(spectator.component.addToCart, 'emit');

Gracias al typing de TypeScript, si escribes una función que no existe en addToCart, el editor te avisa al instante. Así te aseguras de espiar solo métodos válidos.

Por qué los spies se crean antes de renderizar el componente

En el minuto [4:20] se explica que todos los spies deben declararse antes de que el componente se renderice. Por eso conviene controlar el momento del render manualmente, en lugar de dejar que Spectator lo haga automáticamente al inicio.

Si el componente ya corrió, el espía llega tarde y no captura las llamadas iniciales.

Qué es el patrón AAA en testing y cómo aplicarlo

El patrón de las tres A es la estructura recomendada para escribir pruebas claras y mantenibles. Se menciona en el minuto [4:50] y se compone de:

  • Arrange: alistas el entorno, los spies, los datos de entrada y todo lo necesario.
  • Act: ejecutas la acción que quieres probar, como un clic o la llamada a un método.
  • Assert: verificas tus hipótesis con expect.

Separar tu prueba en estos tres bloques hace que cualquier persona del equipo entienda qué estás probando sin leer entre líneas.

¿Qué significa AAA en unit testing? Arrange, Act, Assert. Es el patrón que organiza una prueba en tres pasos: preparar el contexto, ejecutar la acción y validar el resultado esperado.

Por qué probar el clic del botón en lugar de la función directamente

Aquí viene lo interesante. Podrías hacer spectator.component.addToCart() y la prueba pasaría. Pero el usuario real nunca llama a esa función: hace clic en un botón. Si pruebas solo la función, podrías borrar el (click) del template y la prueba seguiría pasando, ocultando un bug serio.

La solución es agregar un data-testid al botón y simular el clic real:

html <button data-testid="add-to-cart-button" (click)="addToCart()"> Add to cart </button>

Luego, en la prueba, Spectator simplifica todo:

typescript spectator.click(byTestId('add-to-cart-button')); expect(emitSpy).toHaveBeenCalledWith(product);

Con esto pruebas tres cosas a la vez: que el botón existe, que tiene el evento atado y que el emit se dispara con el producto correcto.

Cómo emular acciones del usuario en componentes

La regla de oro al probar componentes es pensar como el usuario. Si interactúa con un clic, simula el clic. Si abre un dropdown, simula la apertura. Esa es la diferencia entre un test que protege tu código y uno que solo da una falsa sensación de seguridad.

En servicios el contexto cambia: ahí sí ejecutas la función directamente porque no hay UI de por medio.

¿Cuándo uso jest.spyOn vs jest.fn? Usa jest.fn() cuando creas un mock completo desde cero, normalmente para inyección de dependencias. Usa jest.spyOn() cuando quieres observar un método existente, como un emit en un EventEmitter.

Habilidades y conceptos clave de esta clase

  • Spies en Jest [0:15]: técnica para trackear llamadas a funciones sin alterar su lógica.
  • jest.spyOn sobre EventEmitter [3:10]: la forma correcta de espiar un @Output() de Angular.
  • Patrón AAA [4:50]: arrange, act, assert como estructura mental de toda buena prueba.
  • data-testid [6:30]: atributo recomendado para seleccionar elementos en pruebas sin acoplarse a clases CSS.
  • byTestId con Spectator [7:00]: helper que simplifica query y click en un solo paso.
  • Testing centrado en el usuario [7:40]: probar interacciones reales como clics, no llamadas internas a métodos.

En la siguiente clase verás cómo escribir pruebas para componentes que sí tienen inyección de dependencias y servicios. ¿Tú ya aplicas el patrón AAA en tus pruebas o tienes otro flujo? Cuéntalo en los comentarios.