Contenido del curso
0:00/14:33
Probar hooks que consumen APIs sin depender del backend real es uno de los retos más comunes en testing de React. Con Mock Service Worker (MSW) puedes interceptar las requests HTTP y validar que tu hook useOrders se comporte como esperas, usando un servidor simulado en lugar de mocks manuales o spies.
¿Cómo se estructura un test de hook con Mock Service Worker?
La idea es renderizar el hook dentro de un wrapper que provea el contexto necesario, y dejar que MSW intercepte las llamadas reales del hook.
En este enfoque cambias la estrategia respecto a clases anteriores. Antes mockeabas todo: el proveedor de sesión, las rutas y la respuesta del fetch. Ahora solo mockeas la sesión y dejas que MSW responda al endpoint de órdenes como lo haría un servidor real.
Los pasos clave son tres:
useOrdersMSW.test.tsx, solo con fines educativos.describe, it y expect desde vitest, y renderHook desde testing library.SessionProvider y MemoryRouter mediante un wrapper.¿Qué es Mock Service Worker? Es una utilidad que intercepta requests HTTP a nivel de red y devuelve respuestas simuladas definidas en handlers, sin tocar tu código de producción. [04:30]
¿Por qué se usa un wrapper en lugar de mockear los providers?
Un wrapper permite envolver el hook con los contextos reales que necesita para funcionar. Es más cercano a un test de integración que a un test puramente unitario.
La función renderHook acepta como segundo argumento un objeto con la propiedad wrapper. Ahí pasas un componente que recibe children: React.ReactNode y los envuelve en los providers:
tsx const wrapper = ({ children }: { children: React.ReactNode }) => ( <SessionProvider> <MemoryRouter>{children}</MemoryRouter> </SessionProvider> );
La diferencia con la versión basada en mocks es directa: en aquel caso, renderHook(useOrders) recibía solo el hook porque todo estaba mockeado por fuera. Aquí, en cambio, le pasas { wrapper } para que el hook viva dentro de un entorno realista. [03:10]
¿Cómo se mockea solo la sesión sin tocar las órdenes?
El hook useOrders necesita autenticación para funcionar, así que el useSession sí se mockea. Pero las órdenes ya no: de eso se encarga MSW.
Usas vi.mock apuntando a la ruta del AuthContext, y dentro retornas el módulo real con await vi.importActual más una versión falsa de useSession creada con vi.fn(). Así conservas el SessionProvider original pero controlas qué devuelve el hook de sesión.
Un detalle importante: useSession retorna un valor, no una promesa. Si lo mockeas con mockResolvedValue el test queda colgado en timeout. La solución es usar mockReturnValue para que devuelva directamente el objeto del usuario. [07:50]
¿Cómo se valida que el hook obtuvo la data correcta?
Dentro del it, ejecutas renderHook(useOrders, { wrapper }) y desestructuras result y waitForNextUpdate. El flujo de aserciones cubre dos momentos del ciclo de vida del hook.
Primero verificas el estado inicial:
initialLoading debe ser true antes de que la request responda.Luego esperas con await waitForNextUpdate() a que MSW responda, y validas el resultado:
result.current.orders.length debe ser 1, porque el handler configurado en la clase anterior retorna exactamente una orden.2, el test falla, lo que demuestra que la respuesta viene realmente del servidor simulado.¿Por qué el test espera una sola orden? Porque el handler de MSW configurado para el endpoint de órdenes retorna un único producto. El número en la aserción debe coincidir con lo que define ese handler. [09:15]
¿Qué hacer cuando el test queda en timeout?
El error timeout waitForNextUpdate suele indicar que el hook nunca avanza de estado. Revisa primero cómo estás mockeando dependencias síncronas como useSession.
La regla es simple: usa mockResolvedValue solo cuando el valor original es una promesa. Para getters que devuelven estado plano, usa mockReturnValue. Confundir ambos rompe la cadena de actualizaciones del hook y bloquea el test.
Con esta base ya puedes probar respuestas exitosas. ¿Y cuándo el servidor falla con un error 500? Cuéntame en los comentarios cómo manejas tú esos casos en tus pruebas.
Marlon Ortega
Para los que están usando node 18
usen: await act(async () => { });
en reemplazo de : await waitForNextUpdate();
Wilmer Garzon Cabezas
Team PlatziGracias por tu aporte Marlon! 💚
Yakira Jaraba pineda
import { renderHook } from '@testing-library/react-hooks'; con eso se solucciona igual
Mariano Ostric
Puede ser que falta una clase en la que se cofiguren los mocks? el handler.ts y server.ts ? esta es la parte 1 de testing de APIs externas con MSW y ni siquiera descargamos las dependencias.
por si alguien la quiere descargar, la dejo por aca
npm i msw
y unos ejemplos de uso por aca
David Martínez López
Parece que el orden de las clases está mal, en la que tiene por nombre "Mock Service Worker (MSW)" esta la configuración que se menciona.
Wilmer Garzon Cabezas
Team PlatziIssue corregido Mariano, gracias por la anotación! 💚
Mariana Valencia Gallego
No conocía MSW y creo que tiene potencial para hacer que los proyectos en los que he trabajado fueran mucho más placenteros de probar.
Wilmer Garzon Cabezas
Team PlatziExacto! es una gran alternativa para no llenar de mocks estaticos nuestros proyectos 💚