Angular 21 de Cero a Experto / Nivel producción
Testing: probar como usa un usuario
Una app sin tests es una app que da miedo cambiar: cada modificación puede romper algo sin que te enteres hasta producción. Los tests son la red de seguridad que te deja refactorizar y crecer con confianza. Hoy aprendes a testear en Angular con TestBed y Angular Testing Library —probando el COMPORTAMIENTO como lo vive un usuario, no los detalles internos—, y consolidas la mentalidad con un mini-verificador en vivo.
La red del trapecista
Testear lógica pura (lo más fácil y valioso)
Todo lo que separaste en funciones puras —tu store, tus validadores, tus derivados— se testea sin Angular, con Vitest. Es rápido y cubre la lógica de negocio:
import { describe, it, expect } from 'vitest';
import { calcularTotal, filtrarPorCategoria } from './gastos.logica';
describe('lógica de gastos', () => {
it('calcula el total de una lista', () => {
const gastos = [{ valor: 4500 }, { valor: 18000 }];
expect(calcularTotal(gastos)).toBe(22500);
});
it('el total de una lista vacía es 0', () => {
expect(calcularTotal([])).toBe(0);
});
it('filtra por categoría', () => {
const gastos = [{ categoria: 'comida' }, { categoria: 'ocio' }];
expect(filtrarPorCategoria(gastos, 'comida')).toHaveLength(1);
});
});Por eso vale la pena separar la lógica de la UI (como hiciste con los validadores y el store): se testea aislada, rápida, sin montar componentes. Es donde vive el mayor valor por esfuerzo.
Testear componentes con Angular Testing Library
Para probar un componente, Angular Testing Library te anima a interactuar como un USUARIO —buscar por rol/texto, hacer clic— en vez de inspeccionar internos:
import { render, screen } from '@testing-library/angular';
import userEvent from '@testing-library/user-event';
import { ContadorComponent } from './contador.component';
it('incrementa el contador al hacer clic', async () => {
await render(ContadorComponent);
// el usuario ve "Gastos: 0"
expect(screen.getByText('Gastos: 0')).toBeTruthy();
// el usuario hace clic en el botón
await userEvent.click(screen.getByRole('button', { name: /agregar/i }));
// ahora ve "Gastos: 1"
expect(screen.getByText('Gastos: 1')).toBeTruthy();
});La pirámide de tests
Pruébalo: un mini-verificador de tests, en vivo
Vitest no corre en el sandbox, pero la ESENCIA de un test —ejecutar código y afirmar que el
resultado es el esperado— es simple. Aquí, un mini describe/it/expect que prueba la lógica
del store, corriendo de verdad:
Observa: describe agrupa, it ejecuta cada caso atrapando errores (verde si pasa, rojo si la
afirmación falla), y expect(...).toBe(...) lanza si el resultado no coincide. Vitest es esto
con muchísimas más afirmaciones y utilidades, pero el corazón es el que ves. Fíjate en el test
que falla a propósito: así se ve una red de seguridad haciendo su trabajo —te avisa exactamente
qué esperaba y qué recibió—.
¿Por qué se recomienda testear el COMPORTAMIENTO (lo que el usuario ve y hace) en vez de la IMPLEMENTACIÓN (métodos y propiedades internas)?
Mini-reto
En el playground, añade a tu mini-framework: 1) un matcher toEqual que compare arrays/objetos
(por JSON); 2) tests para una función saldo(presupuesto, gastos) que devuelva
presupuesto - total; 3) un test que verifique que filtrar por una categoría inexistente
devuelve []. Escribe al menos un test que falle a propósito y confírmalo en rojo.
Qué sigue
Tu app está probada y da confianza para crecer. Cierras la teoría del módulo con dos temas de apps profesionales: la internacionalización (i18n) para llegar a más usuarios, y los monorepos con Nx para organizar proyectos grandes. La próxima lección, antes del reto final del módulo.