Unit Tests — Guía de Aprendizaje
📌 Contexto de la sesión: Esta página nació durante una clase en vivo sobre unit tests (agosto 2026). La teoría está completada y ya hay tests reales en el repo (user-service y time-entry-service). El siguiente reto (issue T-03) es ampliar la cobertura a board/task/column/workspace.
Estado actual
Sección titulada «Estado actual»| Fase | Estado |
|---|---|
| Teoría con ejemplos ficticios | ✅ Completada |
| Instalar Vitest | ✅ vitest en apps/web (vitest.config.ts, script pnpm test) |
| Primer test real | ✅ server/user/service/user-service.test.ts (verifyCredentials + registerUser) |
| Segundo test real | ✅ server/time-entry/service/time-entry-service.test.ts (computeTaskMetrics) |
| CI ejecuta los tests | 🟡 En curso — CI actualmente corre lint + typecheck (T-03 amplía cobertura) |
Resumen de lo aprendido
Sección titulada «Resumen de lo aprendido»¿Qué es un unit test?
Sección titulada «¿Qué es un unit test?»Código que prueba automáticamente que una función hace lo que debe, de forma aislada (sin BD, sin red).
Las 3 fases: AAA
Sección titulada «Las 3 fases: AAA»| Fase | Significado | Ejemplo |
|---|---|---|
| Arrange | Preparar datos de entrada | Crear usuario falso |
| Act | Ejecutar la función | verifyCredentials("ana@...", "demo1234") |
| Assert | Verificar resultado | expect(result).not.toBeNull() |
¿Qué es un mock?
Sección titulada «¿Qué es un mock?»Un objeto falso que sustituye a una dependencia real. En Syncro, mockearemos los repositorios (Prisma) para testear los servicios sin BD.
Herramientas de aserción
Sección titulada «Herramientas de aserción»| Comando | Significado |
|---|---|
expect(x).toBe(y) |
“x debe ser exactamente y” |
expect(x).not.toBeNull() |
“x no debe ser null” |
expect(() => fn()).toThrow("msg") |
“fn debe lanzar error con mensaje msg” |
Dónde escribir los tests
Sección titulada «Dónde escribir los tests»Regla: co-ubicación. Cada test vive al lado del archivo que testea:
server/user/service/├── user-service.ts└── user-service.test.ts ← tests de verifyCredentials, registerUser ✅
server/task/service/├── task-service.ts└── task-service.test.ts ← tests de createTaskService, updateTaskService... (T-03)
server/time-entry/service/├── time-entry-service.ts└── time-entry-service.test.ts ← tests de computeTaskMetrics ✅Nomenclatura: [nombre-del-archivo].test.ts
Ejecutar los tests
Sección titulada «Ejecutar los tests»Desde apps/web:
pnpm test # vitest run (una vez)pnpm test:watch # modo watchFunciones candidatas para testear (T-03)
Sección titulada «Funciones candidatas para testear (T-03)»user-service.ts ✅ (hecho)
Sección titulada «user-service.ts ✅ (hecho)»verifyCredentials(email: string, password: string)registerUser(data: { email, password, name })time-entry-service.ts ✅ (hecho)
Sección titulada «time-entry-service.ts ✅ (hecho)»computeTaskMetrics(task, entries); // invertido, desviación y % de estimacióntask-service.ts, board-service.ts, column-service.ts, workspace-service.ts (pendiente T-03)
Sección titulada «task-service.ts, board-service.ts, column-service.ts, workspace-service.ts (pendiente T-03)»createTaskService(workspaceId, userId, data)updateTaskService(taskId, userId, data)deleteTaskService(taskId, userId)createBoardService(...)updateMemberRoleService(...)Próximos pasos (issue T-03)
Sección titulada «Próximos pasos (issue T-03)»- Ampliar la cobertura a
task-service,board-service,column-serviceyworkspace-service. - Mantener las funciones probadas puras (sin dependencia directa de Prisma en la lógica a testear).
- Opcional: añadir los tests al workflow de CI (job
test).
Recursos externos
Sección titulada «Recursos externos»- Documentación de Vitest
- Guía de expect en Vitest
- Discord de Syncro — para dudas o pedir ayuda
✏️ Nota para la próxima sesión: Dile al asistente “continúa la clase de unit tests, lee la guía en
apps/docs/src/content/docs/backend/unit-tests.md” para retomar exactamente donde lo dejamos.