Skip to content

Test: cobertura del hallazgo #2 (P0 + P1) — spring-security-test, JwtRequestFilter y @WebMvcTest de los 23 controllers

belen.varsi requested to merge pft/feature/security-tests-p0 into master

Qué

Cierra el hallazgo #2 (Alto) de la auditoría de backend (2026-08-27):
antes de esta rama, controller tenía 0% de cobertura de tests y
security apenas 1%, pese a ser las capas que deciden si una request
con datos confidenciales de estudiantes pasa o no.

Esta MR cubre tanto el P0 (autorización real end-to-end) como el P1
(contrato HTTP) de ese hallazgo. Los 23 controllers del proyecto quedan
con al menos un test.

P0 — Autorización real (spring-security-test + JwtRequestFilter + comentarios confidenciales)

  • pom.xml: agrega spring-security-test.
  • JwtRequestFilterTest (9 casos, 100% de cobertura de instrucciones y
    ramas del filtro): tokens reales firmados con JJWT, no mockeados —
    sin header, malformado, firma manipulada, vencido, usuario no
    encontrado, credenciales no vigentes (password cambiada después de
    emitido el token), válido, y el guard de "ya autenticado".
  • ComentarioConfidencialEstudianteControllerTest /
    ComentarioConfidencialInstanciaControllerTest: los dos endpoints
    con datos más sensibles del sistema. Deliberadamente no usan
    @WebMvcTest — en este proyecto @PreAuthorize vive en el service,
    no en el controller, y @WebMvcTest reemplaza el service por un
    mock que nunca ejecutaría esa autorización. Usan @SpringBootTest
    con el contexto completo (service real, proxy de seguridad real) y
    solo los repositorios mockeados, para que la request atraviese de
    verdad: JwtRequestFilter@PreAuthorize real →
    GlobalExceptionHandler. Cubren, por endpoint de listar/crear: sin
    token (401), sin permiso (403), con permiso (200/201), y contenido
    en blanco (400, Bean Validation real).

P1 — Contrato HTTP del resto de los controllers

Para los 20 controllers restantes, el objetivo no es la autorización
(ya cubierta en el P0) sino el contrato de entrada/salida: @Valid
→ 400, 404/409/422 propagados desde el service, forma del JSON de
respuesta. Por eso acá sí se usa @WebMvcTest clásico con el service
mockeado — es la herramienta correcta para esto.

AbstractControllerTest (clase base nueva) evita repetir en cada
uno de los 20 controllers el mismo boilerplate de infraestructura:

  • Mocks de CustomUsuarioDetailsService y JwtTokenUtil:
    JwtRequestFilter se carga en cualquier @WebMvcTest (es un
    Filter) y depende de ambos en su constructor.
  • Mock de CacheManager: @EnableCaching vive en SienepApplication, la @SpringBootConfiguration que usa cualquier @WebMvcTest como
    base, sin importar si el controller bajo test cachea algo o no.
  • @WithMockUser a nivel de clase.
  • Un ObjectMapper propio con .findAndRegisterModules() — sin esto,
    Jackson falla con "Java 8 date/time type not supported by default"
    al (de)serializar LocalDate/LocalDateTime, muy comunes en los
    DTOs de este proyecto.

Controllers cubiertos: Auditoria, Auth, Carrera, CategoriaInstancia,
CategoriaRecordatorio, ComentarioNormalEstudiante,
ComentarioNormalInstancia, Estudiante, Frecuencia, Funcionario, Grupo,
Incidencia, InformeAdjunto, InstanciaComun, Involucrado, Itr, Permiso,
Recordatorio, Reporte, Rol, Telefono.

Testing

  • Suite completa: 695 tests, 0 failures (516 base + 21 del P0 + 158
    nuevos del P1).
  • Cobertura JaCoCo:
    • JwtRequestFilter: 0% → 100% instrucciones y ramas.
    • Paquete controller completo: 0% → 63% instrucciones, 44% ramas
      — las 23 clases con al menos un test.

Qué queda del hallazgo #2 (fuera de esta MR)

  • Ampliar cobertura a endpoints menos comunes por controller
    (obtenerPorId/editar/eliminar donde solo se cubrió crear/listar).
  • @DataJpaTest para los repositories con @Query custom de mayor
    riesgo (la otra mitad del P1 de la sección 5 de la auditoría).
  • Test que fije cuál UserDetailsService se usa en cada flujo de
    autenticación (warning de arranque "Found 2 UserDetailsService beans").

Merge request reports

Loading