Mockear getOrders y probar el dashboard

Resumen

Probar que un dashboard renderice correctamente los pedidos provenientes de una API es uno de los retos más comunes al testear componentes en React con Vitest. Aquí aprenderás a mockear servicios, contextos de sesión y validar el renderizado de listas usando Testing Library.

Este flujo es útil para quienes desarrollan aplicaciones con autenticación basada en roles y necesitan asegurar que la UI muestre los datos correctos según el usuario logueado.

¿Qué se prueba en el test del dashboard de órdenes?

El objetivo es verificar que las órdenes devueltas por el endpoint /orders se rendericen efectivamente en el componente. En el proyecto, un backend dummy corre en el puerto 3001 y expone un arreglo orders desde db.json, que sirve como referencia para construir los datos mockeados [00:25].

La estructura inicial vive en src/containers/orders/orders.test.tsx y arranca con el patrón clásico de Vitest: describe, it y expect importados desde vitest [01:05].

¿Qué es mockear en testing? Es reemplazar una función o módulo real por una versión controlada que devuelve datos predecibles, para aislar el comportamiento del componente que estás probando.

¿Cómo mockear servicios y contextos en Vitest?

El componente Orders depende de dos piezas externas: la función getOrders, que retorna una promesa con los pedidos, y el hook useSession, que valida si hay un usuario autenticado [02:30].

Para getOrders se usa vi.mock apuntando a la ruta ../../services/getOrders, declarando la función como vi.fn(). Esto permite controlar qué datos retorna durante el test.

Para useSession, que vive en context/AuthContext, se necesita preservar el resto del módulo. Aquí entra vi.importActual, que importa el contenido real del archivo y solo sobrescribe la función específica que quieres reemplazar [03:45].

tsx vi.mock('../../context/AuthContext', async () => { const actual = await vi.importActual('../../context/AuthContext'); return { ...actual, useSession: vi.fn(), }; });

¿Por qué usar vi.importActual?

Porque AuthContext exporta varias utilidades, entre ellas SessionProvider, que sigue siendo necesario para envolver el componente. Si mockearas todo el módulo sin importActual, perderías ese provider y el render fallaría.

¿Cómo simular un usuario con rol específico?

La aplicación maneja dos roles: superadmin y visualizer. Para probar el caso del visualizador, la función handleRenderOrders recibe un parámetro userRole que construye un mockUser dinámico [05:10].

tsx const handleRenderOrders = (userRole) => { const mockUser = userRole ? { role: userRole } : null; (useSession as Mock).mockReturnValue({ user: mockUser });

mockGetOrders.mockResolvedValue(mockOrders);

render( <MemoryRouter> <SessionProvider> <Orders /> </SessionProvider> </MemoryRouter> ); };

La clave está en mockReturnValue, que define qué devuelve useSession cuando el componente lo invoca, y en mockResolvedValue, que resuelve la promesa de getOrders con el arreglo mockOrders preparado previamente [06:20].

¿Cómo validar que se rendericen todas las órdenes?

Como getOrders es asíncrono, la aserción debe envolverse en waitFor, importado desde @testing-library/react. Sin esa espera, el test consultaría el DOM antes de que React procese la respuesta [07:40].

Para contar los elementos renderizados se usa getAllByRole, una query que retorna un arreglo en lugar de un solo elemento. Cada OrderItem contiene un <h3>, así que la consulta busca elementos con rol heading y nivel 3.

tsx it('debería mostrar las órdenes', async () => { handleRenderOrders('Visualizer');

await waitFor(() => { const orders = screen.getAllByRole('heading', { level: 3 }); expect(orders).toHaveLength(mockOrders.length); }); });

¿Cuándo usar getAllByRole en vez de getByRole? Usa getAllByRole cuando esperes múltiples elementos del mismo tipo, como en listas. Devuelve un arreglo y permite validar la cantidad con toHaveLength.

¿Cómo confirmar que el test realmente funciona?

Una forma práctica es forzar un fallo. Si mockOrders tiene una sola posición y cambias la aserción a toHaveLength(2), el test debe fallar. Al volver a mockOrders.length, vuelve a pasar [08:55]. Esta técnica confirma que la prueba evalúa lo correcto y no pasa por accidente.

Habilidades y conceptos aplicados

  • Mocking de módulos con vi.mock: reemplaza dependencias externas por versiones controladas [02:30].
  • vi.importActual: importa el módulo real para preservar exports que sí necesitas [03:45].
  • mockReturnValue y mockResolvedValue: definen qué devuelve un mock síncrono o una promesa [06:20].
  • waitFor: espera asíncrona para validar UI tras resolver promesas [07:40].
  • getAllByRole con level: localiza múltiples elementos por rol semántico [08:10].
  • toHaveLength: aserción específica para arreglos.
  • MemoryRouter y SessionProvider: wrappers necesarios para que el componente reciba el contexto de routing y sesión.

Hasta acá ya recorriste unit testing, UI testing, table-driven testing y test-driven development, recordando que TDD aplica a software que no es experimental. ¿Qué parte te ha resultado más reveladora? Cuéntalo en la sección de aportes.