Contenido del curso
Pruebas de Servicios y Dependencias
- 5

Spectator para unit tests en Angular
03:35 min - 6

Pruebas de Pipes en Angular con Spectator y Jest
10:08 min - 7

Genera unit tests en Angular con AI
13:40 min - 8

Cómo testear servicios Angular con Spectator
15:10 min - 9

Creación de Datos Simulados con la Librería Faker.js
10:39 min - 10

Pruebas Unitarias para Servicios con Inyección de Dependencias en Angular
15:58 min - 11

Pruebas Unitarias con Mocking en MetaTax Service
08:28 min - 12

Pruebas de Servicios HTTP Client en Angular con Spectarer y Jest
15:08 min
Pruebas de Componentes
- 13

jest-fetch-mock para pruebas con fetch
09:55 min - 14

Mocking de APIs Globales en JavaScript para Pruebas Unitarias
09:33 min - 15

Pruebas Unitarias de Componentes en Angular con Spectator
11:51 min - 16

data-testid para queries en componentes Angular
07:26 min - 17

Cómo espiar Outputs con jest.spyOn en Angular
10:28 min - 18

Unit Testing para Componentes con Inyección de Dependencias
15:13 min
Casos Prácticos y Aplicaciones
- 19

Mocking y pruebas unitarias en Angular: Inyección de dependencias
10:20 min - 20

Pruebas Complejas en Angular: Testing de Componentes y Servicios
15:22 min - 21

Pruebas de Mocking y Deferred Components en Angular
Viendo ahora - 22

Pruebas de Interacción en Componentes Angular: Galería de Imágenes
08:46 min - 23

Múltiples dependencias mockeadas en Angular
08:03 min
Pruebas de Mocking y Deferred Components en Angular
Resumen
Probar componentes con carga diferida en Angular tiene un truco escondido: el IntersectionObserver API no existe en el entorno de pruebas y rompe la consola aunque los tests pasen. Aquí aprendes a mockear esa API, controlar manualmente el bloque defer y verificar que tu componente diferido se renderice como esperas.
Por qué falla IntersectionObserver en los tests de Angular
Cuando corres pruebas unitarias sobre un componente que usa @defer con la condición on viewport, la consola te lanza un error: IntersectionObserver is not defined. Los tests pasan, pero ese mensaje incomoda y revela algo importante sobre cómo Angular carga estos bloques.
Qué hace Angular por detrás cuando usas defer on viewport
Angular utiliza la IntersectionObserver API, una API nativa del navegador que detecta cuándo un elemento entra al viewport del usuario. Es la misma lógica que aplica para APIs como navigator.geolocation o fetch: existen del lado del browser, no del lado del runtime de pruebas [03:15].
El entorno de testing no es un navegador real, es un entorno controlado que monta componentes pero no expone todas las APIs nativas. Por eso, cuando el componente diferido intenta inicializarse, no encuentra IntersectionObserver y revienta.
¿Qué es IntersectionObserver? Es una API del navegador que avisa cuándo un elemento entra o sale del viewport. Angular la usa internamente para decidir cuándo cargar bloques
defer on viewport.
Cómo crear un mock de IntersectionObserver
La solución es suplantar la API directamente sobre el objeto window, igual que harías con fetch. El mock reemplaza la API nativa con funciones vacías que simulan los métodos esperados: observe, unobserve y disconnect.
typescript (window as any).IntersectionObserver = jest.fn().mockImplementation(() => ({ observe: jest.fn(), unobserve: jest.fn(), disconnect: jest.fn(), }));
Con ese mocking, el error desaparece de la consola y las pruebas siguen pasando limpias. Como las funciones están envueltas en jest.fn(), también podrías espiarlas más adelante si necesitas verificar que algo las llamó.
Cómo probar manualmente un bloque defer en pruebas unitarias
Una vez resuelto el error, viene la pregunta de fondo: cómo verificar que el componente dentro del @defer realmente se renderiza. En unit tests no puedes mover el scroll, así que necesitas tomar control manual del bloque diferido.
Configurar deferBlockBehavior en modo manual
En la creación del componente con Spectator (o TestBed), agregas el parámetro deferBlockBehavior y lo defines como Manual. Este enum viene de @angular/core/testing [07:30].
typescript import { DeferBlockBehavior } from '@angular/core/testing';
const createComponent = createComponentFactory({ component: ProductDetailComponent, deferBlockBehavior: DeferBlockBehavior.Manual, });
Con esto le dices al runtime: no intentes detectar viewport, yo te aviso cuándo cargar. Eso te da control total para probar cada estado del bloque.
Renderizar el bloque defer con renderComplete
Dentro del it, llamas a spectator.deferBlock() y le pasas el método que quieres simular. Las opciones cubren todos los estados que puede tener un @defer:
renderComplete: simula que el contenido principal terminó de cargar.renderLoading: simula el estado de carga.renderError: simula un error en la carga.renderPlaceholder: simula el placeholder antes de cargar.
Como renderComplete es asíncrono, el test se vuelve async y le agregas await:
typescript it('should load related products', async () => { spectator.detectChanges(); await spectator.deferBlock().renderComplete(); expect(spectator.query(RelatedComponent)).toBeTruthy(); });
¿Cómo verifico que un componente Angular se renderizó dentro de un defer? Pasa la clase del componente directamente a
spectator.query(), sin necesidad de undata-testid. Funciona cuando es un componente Angular, no un tag HTML genérico.
Por qué consultar por clase del componente y no por testid
Cuando el elemento renderizado es un componente Angular como RelatedComponent, puedes pasarle la clase directamente a query. Esto es más limpio que añadir un data-testid y te ahorra acoplar el test al markup interno del hijo.
Qué probar más allá del renderComplete
El modo manual te abre la puerta a escenarios que en producción son difíciles de reproducir.
- Verifica el estado de loading mientras el bloque está cargando.
- Valida el mensaje o componente de error cuando algo falla.
- Confirma que el placeholder se muestra antes de iniciar la carga.
- Comprueba que servicios como
getOneBySlugfueron llamados con los argumentos correctos.
Cada uno de esos casos se prueba reemplazando renderComplete() por el método correspondiente y consultando el DOM resultante.
En la siguiente clase viene un reto distinto: probar la galería de imágenes, donde los data-testid se duplican y toca buscar otra estrategia para identificar elementos. ¿Has tenido que lidiar con IntersectionObserver en tus tests? Cuéntame cómo lo resolviste.