1+ import unittest
2+ from unittest .mock import Mock
3+
4+ from services .empleado_service import EmpleadoService
5+ from modules .persistence import ManejadorPersistencia
6+ from models .empleado import Empleado
7+
8+
9+ class EmpleadosTests (unittest .TestCase ):
10+ """
11+ Clase de pruebas unitarias para el servicio de empleados.
12+ Utiliza Mock para aislar las pruebas de la capa de persistencia (sin IO real).
13+ """
14+
15+ def setUp (self ):
16+ """
17+ Configuración inicial que se ejecuta antes de cada prueba.
18+ Crea un mock de ManejadorPersistencia y una instancia del servicio.
19+ """
20+ self .mock_persistencia = Mock (spec = ManejadorPersistencia )
21+ self .service = EmpleadoService (self .mock_persistencia )
22+
23+ self .lista_empleados_iniciales = [
24+ {"id" : 1 , "nombre" : "Ana Pérez" , "rol" : "Desarrollador" },
25+ {"id" : 2 , "nombre" : "Luis Gómez" , "rol" : "Analista" }
26+ ]
27+
28+ def test_excepciones_creacion_modelo_empleado (self ):
29+ """
30+ Prueba que el modelo Empleado valide correctamente los parámetros.
31+ Debe lanzar ValueError cuando se proporcionan datos inválidos.
32+ """
33+ with self .assertRaises (ValueError ):
34+ Empleado ("1" , "Daniel Yanes" , "Cybersecurity Analyst" )
35+
36+ with self .assertRaises (ValueError ):
37+ Empleado (- 999 , "Daniel Yanes" , "Cybersecurity Analyst" )
38+
39+ with self .assertRaises (ValueError ):
40+ Empleado (1 , 999 , "Cybersecurity Analyst" )
41+
42+ with self .assertRaises (ValueError ):
43+ Empleado (1 , "Daniel Yanes" , 999 )
44+
45+ def test_str_representacion_modelo_empleado (self ):
46+ """
47+ Prueba la representación en string del modelo Empleado.
48+ """
49+ empleado_creado = Empleado (1 , "Daniel Yanes" , "Cybersecurity Analyst" )
50+
51+ self .assertEqual (
52+ empleado_creado .__str__ (),
53+ "Empleado(id=1, nombre='Daniel Yanes', rol='Cybersecurity Analyst')"
54+ )
55+
56+ def test_obtener_todos_empleados (self ):
57+ """
58+ Prueba la obtención de todos los empleados.
59+ Verifica que se carguen los datos correctamente y se retorne la lista completa.
60+ """
61+ datos = {
62+ "proyectos" : [],
63+ "empleados" : self .lista_empleados_iniciales ,
64+ "tareas" : [],
65+ "asignaciones" : []
66+ }
67+ self .mock_persistencia .cargar_datos .return_value = datos
68+
69+ resultado = self .service .obtener_todos ()
70+
71+ self .assertEqual (
72+ [{"id" : e .id , "nombre" : e .nombre , "rol" : e .rol } for e in resultado ],
73+ self .lista_empleados_iniciales
74+ )
75+ self .mock_persistencia .cargar_datos .assert_called_once ()
76+ self .mock_persistencia .guardar_datos .assert_not_called ()
77+
78+ def test_crear_empleado (self ):
79+ """
80+ Prueba la creación de un nuevo empleado.
81+ Verifica que se genere un ID correcto y se guarde en la persistencia.
82+ """
83+ datos = {
84+ "proyectos" : [],
85+ "empleados" : list (self .lista_empleados_iniciales ),
86+ "tareas" : [],
87+ "asignaciones" : []
88+ }
89+ self .mock_persistencia .cargar_datos .return_value = datos
90+ self .mock_persistencia .obtener_proximo_id .return_value = 3
91+
92+ empleado = self .service .crear ("María López" , "QA" )
93+
94+ self .assertEqual (empleado .id , 3 )
95+ self .assertEqual (empleado .nombre , "María López" )
96+ self .assertEqual (empleado .rol , "QA" )
97+ self .mock_persistencia .cargar_datos .assert_called_once ()
98+ self .mock_persistencia .guardar_datos .assert_called_once ()
99+ self .assertEqual (len (datos ["empleados" ]), 3 )
100+ self .assertEqual (
101+ datos ["empleados" ][- 1 ],
102+ {"id" : 3 , "nombre" : "María López" , "rol" : "QA" }
103+ )
104+
105+ def test_actualizar_empleado (self ):
106+ """
107+ Prueba la actualización completa de un empleado existente.
108+ Verifica que se actualicen tanto nombre como rol correctamente.
109+ """
110+ datos = {
111+ "proyectos" : [],
112+ "empleados" : list (self .lista_empleados_iniciales ),
113+ "tareas" : [],
114+ "asignaciones" : []
115+ }
116+ self .mock_persistencia .cargar_datos .return_value = datos
117+
118+ actualizado = self .service .actualizar (2 , "Luis G." , "Líder" )
119+
120+ self .assertTrue (actualizado )
121+ self .mock_persistencia .cargar_datos .assert_called_once ()
122+ self .mock_persistencia .guardar_datos .assert_called_once ()
123+ self .assertEqual (datos ["empleados" ][1 ]["nombre" ], "Luis G." )
124+ self .assertEqual (datos ["empleados" ][1 ]["rol" ], "Líder" )
125+
126+ def test_eliminar_empleado (self ):
127+ """
128+ Prueba la eliminación de un empleado.
129+ Verifica que se elimine el empleado y todas sus asignaciones asociadas.
130+ """
131+ datos = {
132+ "proyectos" : [],
133+ "empleados" : list (self .lista_empleados_iniciales ),
134+ "tareas" : [],
135+ "asignaciones" : [
136+ {"id" : 1 , "id_tarea" : 1 , "id_empleado" : 2 , "horas" : 4.0 },
137+ {"id" : 2 , "id_tarea" : 2 , "id_empleado" : 1 , "horas" : 2.0 }
138+ ]
139+ }
140+ self .mock_persistencia .cargar_datos .return_value = datos
141+
142+ eliminado = self .service .eliminar (2 )
143+
144+ self .assertTrue (eliminado )
145+ self .mock_persistencia .cargar_datos .assert_called_once ()
146+ self .mock_persistencia .guardar_datos .assert_called_once ()
147+ self .assertEqual (len (datos ["empleados" ]), 1 )
148+ self .assertFalse (any (e ["id" ] == 2 for e in datos ["empleados" ]))
149+ self .assertFalse (
150+ any (a ["id_empleado" ] == 2 for a in datos ["asignaciones" ])
151+ )
152+
153+ def test_obtener_por_id_empleado (self ):
154+ """
155+ Prueba la obtención de un empleado por su ID cuando existe.
156+ """
157+ datos = {
158+ "proyectos" : [],
159+ "empleados" : self .lista_empleados_iniciales ,
160+ "tareas" : [],
161+ "asignaciones" : []
162+ }
163+ self .mock_persistencia .cargar_datos .return_value = datos
164+
165+ resultado = self .service .obtener_por_id (1 )
166+
167+ self .assertIsNotNone (resultado )
168+ self .assertEqual (resultado .id , 1 )
169+ self .assertEqual (resultado .nombre , "Ana Pérez" )
170+
171+ def test_obtener_por_id_empleado_no_existe (self ):
172+ """
173+ Prueba la obtención de un empleado por ID cuando no existe.
174+ Debe retornar None
175+ """
176+ datos = {
177+ "proyectos" : [],
178+ "empleados" : self .lista_empleados_iniciales ,
179+ "tareas" : [],
180+ "asignaciones" : []
181+ }
182+ self .mock_persistencia .cargar_datos .return_value = datos
183+
184+ resultado = self .service .obtener_por_id (999 )
185+
186+ self .assertIsNone (resultado )
187+
188+ def test_actualizar_empleado_solo_nombre (self ):
189+ """
190+ Prueba la actualización parcial de un empleado (solo nombre).
191+ """
192+ datos = {
193+ "proyectos" : [],
194+ "empleados" : list (self .lista_empleados_iniciales ),
195+ "tareas" : [],
196+ "asignaciones" : []
197+ }
198+ self .mock_persistencia .cargar_datos .return_value = datos
199+
200+ actualizado = self .service .actualizar (1 , "Nuevo Nombre" )
201+
202+ self .assertTrue (actualizado )
203+ self .assertEqual (datos ["empleados" ][0 ]["nombre" ], "Nuevo Nombre" )
204+ self .assertEqual (datos ["empleados" ][0 ]["rol" ], "Desarrollador" )
205+
206+ def test_actualizar_empleado_solo_rol (self ):
207+ """
208+ Prueba la actualización parcial de un empleado (solo rol).
209+ """
210+ datos = {
211+ "proyectos" : [],
212+ "empleados" : list (self .lista_empleados_iniciales ),
213+ "tareas" : [],
214+ "asignaciones" : []
215+ }
216+ self .mock_persistencia .cargar_datos .return_value = datos
217+
218+ actualizado = self .service .actualizar (1 , rol = "Nuevo Rol" )
219+
220+ self .assertTrue (actualizado )
221+ self .assertEqual (datos ["empleados" ][0 ]["nombre" ], "Ana Pérez" )
222+ self .assertEqual (datos ["empleados" ][0 ]["rol" ], "Nuevo Rol" )
223+
224+ def test_actualizar_empleado_nombre_vacio (self ):
225+ """
226+ Prueba que no se pueda actualizar con nombre vacío.
227+ """
228+ datos = {
229+ "proyectos" : [],
230+ "empleados" : list (self .lista_empleados_iniciales ),
231+ "tareas" : [],
232+ "asignaciones" : []
233+ }
234+ self .mock_persistencia .cargar_datos .return_value = datos
235+
236+ with self .assertRaises (ValueError ):
237+ self .service .actualizar (1 , "" )
238+
239+ def test_actualizar_empleado_nombre_no_string (self ):
240+ """
241+ Prueba que no se pueda actualizar con nombre que no sea string.
242+ """
243+ datos = {
244+ "proyectos" : [],
245+ "empleados" : list (self .lista_empleados_iniciales ),
246+ "tareas" : [],
247+ "asignaciones" : []
248+ }
249+ self .mock_persistencia .cargar_datos .return_value = datos
250+
251+ with self .assertRaises (ValueError ):
252+ self .service .actualizar (1 , 123 )
253+
254+ def test_actualizar_empleado_rol_vacio (self ):
255+ """
256+ Prueba que no se pueda actualizar con rol vacío.
257+ """
258+ datos = {
259+ "proyectos" : [],
260+ "empleados" : list (self .lista_empleados_iniciales ),
261+ "tareas" : [],
262+ "asignaciones" : []
263+ }
264+ self .mock_persistencia .cargar_datos .return_value = datos
265+
266+ with self .assertRaises (ValueError ):
267+ self .service .actualizar (1 , rol = "" )
268+
269+ def test_actualizar_empleado_rol_no_string (self ):
270+ """
271+ Prueba que no se pueda actualizar con rol que no sea string.
272+ """
273+ datos = {
274+ "proyectos" : [],
275+ "empleados" : list (self .lista_empleados_iniciales ),
276+ "tareas" : [],
277+ "asignaciones" : []
278+ }
279+ self .mock_persistencia .cargar_datos .return_value = datos
280+
281+ with self .assertRaises (ValueError ):
282+ self .service .actualizar (1 , rol = 123 )
283+
284+ def test_actualizar_empleado_no_existe (self ):
285+ """
286+ Prueba la actualización de un empleado que no existe.
287+ Debe retornar False.
288+ """
289+ datos = {
290+ "proyectos" : [],
291+ "empleados" : list (self .lista_empleados_iniciales ),
292+ "tareas" : [],
293+ "asignaciones" : []
294+ }
295+ self .mock_persistencia .cargar_datos .return_value = datos
296+
297+ resultado = self .service .actualizar (999 , "Nuevo Nombre" )
298+
299+ self .assertFalse (resultado )
300+
301+ def test_eliminar_empleado_no_existe (self ):
302+ """
303+ Prueba la eliminación de un empleado que no existe.
304+ Debe retornar False.
305+ """
306+ datos = {
307+ "proyectos" : [],
308+ "empleados" : list (self .lista_empleados_iniciales ),
309+ "tareas" : [],
310+ "asignaciones" : []
311+ }
312+ self .mock_persistencia .cargar_datos .return_value = datos
313+
314+ resultado = self .service .eliminar (999 )
315+
316+ self .assertFalse (resultado )
317+
318+
319+ if __name__ == "__main__" :
320+ unittest .main ()
0 commit comments