springboot-verification
Bucle de verificación para proyectos Spring Boot: build, análisis estático, pruebas con cobertura, escaneos de seguridad y revisión de diff antes del lanzamiento o PR.
Resumen
Bucle de Verificación Spring Boot
Ejecutar antes de PRs, después de cambios importantes y antes del despliegue.
Cuándo Activar
- Antes de abrir un pull request para un servicio Spring Boot
- Después de refactorizaciones importantes o actualizaciones de dependencias
- Verificación previa al despliegue para staging o producción
- Ejecutar el pipeline completo de build → lint → test → escaneo de seguridad
- Validar que la cobertura de pruebas cumpla los umbrales
Fase 1: Build
mvn -T 4 clean verify -DskipTests
# o
./gradlew clean assemble -x testSi el build falla, detener y corregir.
Fase 2: Análisis Estático
Maven (plugins comunes):
mvn -T 4 spotbugs:check pmd:check checkstyle:checkGradle (si está configurado):
./gradlew checkstyleMain pmdMain spotbugsMainFase 3: Pruebas + Cobertura
mvn -T 4 test
mvn jacoco:report # verificar cobertura 80%+
# o
./gradlew test jacocoTestReportReporte:
- Total de pruebas, pasadas/fallidas
- % de cobertura (líneas/ramas)
Pruebas Unitarias
Probar la lógica del servicio en aislamiento con dependencias mockeadas:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock private UserRepository userRepository;
@InjectMocks private UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "[email protected]");
var expected = new User(1L, "Alice", "[email protected]");
when(userRepository.save(any(User.class))).thenReturn(expected);
var result = userService.create(dto);
assertThat(result.name()).isEqualTo("Alice");
verify(userRepository).save(any(User.class));
}
@Test
void createUser_duplicateEmail_throwsException() {
var dto = new CreateUserDto("Alice", "[email protected]");
when(userRepository.existsByEmail(dto.email())).thenReturn(true);
assertThatThrownBy(() -> userService.create(dto))
.isInstanceOf(DuplicateEmailException.class);
}
}Pruebas de Integración con Testcontainers
Probar contra una base de datos real en lugar de H2:
@SpringBootTest
@Testcontainers
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("testdb");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired private UserRepository userRepository;
@Test
void findByEmail_existingUser_returnsUser() {
userRepository.save(new User("Alice", "[email protected]"));
var found = userRepository.findByEmail("[email protected]");
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("Alice");
}
}Pruebas de API con MockMvc
Probar la capa controller con el contexto completo de Spring:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private UserService userService;
@Test
void createUser_validInput_returns201() throws Exception {
var user = new UserDto(1L, "Alice", "[email protected]");
when(userService.create(any())).thenReturn(user);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name": "Alice", "email": "[email protected]"}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.name").value("Alice"));
}
@Test
void createUser_invalidEmail_returns400() throws Exception {
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name": "Alice", "email": "not-an-email"}
"""))
.andExpect(status().isBadRequest());
}
}Fase 4: Escaneo de Seguridad
# CVEs de dependencias
mvn org.owasp:dependency-check-maven:check
# o
./gradlew dependencyCheckAnalyze
# Secretos en código fuente
grep -rn "password\s*=\s*\"" src/ --include="*.java" --include="*.yml" --include="*.properties"
grep -rn "sk-\|api_key\|secret" src/ --include="*.java" --include="*.yml"
# Secretos (historial de git)
git secrets --scan # si está configuradoHallazgos Comunes de Seguridad
# Verificar System.out.println (usar logger en su lugar)
grep -rn "System\.out\.print" src/main/ --include="*.java"
# Verificar mensajes de excepción en bruto en respuestas
grep -rn "e\.getMessage()" src/main/ --include="*.java"
# Verificar CORS comodín
grep -rn "allowedOrigins.*\*" src/main/ --include="*.java"Fase 5: Lint/Formato (compuerta opcional)
mvn spotless:apply # si se usa el plugin Spotless
./gradlew spotlessApplyFase 6: Revisión de Diff
git diff --stat
git diffLista de verificación:
- Sin logs de depuración residuales (
System.out,log.debugsin guardias) - Errores y códigos HTTP con significado
- Transacciones y validación presentes donde se necesitan
- Cambios de configuración documentados
Plantilla de Salida
REPORTE DE VERIFICACIÓN
=======================
Build: [PASS/FAIL]
Estático: [PASS/FAIL] (spotbugs/pmd/checkstyle)
Pruebas: [PASS/FAIL] (X/Y pasadas, Z% cobertura)
Seguridad: [PASS/FAIL] (hallazgos CVE: N)
Diff: [X archivos modificados]
General: [LISTO / NO LISTO]
Problemas a Corregir:
1. ...
2. ...Modo Continuo
- Volver a ejecutar las fases ante cambios significativos o cada 30–60 minutos en sesiones largas
- Mantener un bucle corto:
mvn -T 4 test+ spotbugs para retroalimentación rápida
Recuerda: La retroalimentación rápida supera las sorpresas tardías. Mantener la compuerta estricta — tratar las advertencias como defectos en sistemas de producción.
Archivos 1 archivo
Instálala a mano
Deska ejecuta esto por ti, para cada agente que elijas. Para ejecutarlo tú en una terminal:
npx skills add affaan-m/ecc --skill springboot-verificationMás de affaan-m
- docker-patternsaffaan-mDocker and Docker Compose patterns for local development, container security, networking, volume strategies, and multi-service orchestration. Use when setting up containerized development environments or reviewing Docker configurations.4,800 instalaciones en skills.sh0
- security-reviewaffaan-mUse this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment/sensitive features. Provides comprehensive security checklist and patterns.4,800 instalaciones en skills.sh0
- backend-patternsaffaan-mBackend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes. Use when building or reviewing Node.js, Express, or Next.js API routes and their data access.4,700 instalaciones en skills.sh0
- frontend-patternsaffaan-mFrontend development patterns for React, Next.js, state management, performance optimization, and UI best practices. Use when building or reviewing React or Next.js components, state, or render performance.4,700 instalaciones en skills.sh0
- coding-standardsaffaan-mBaseline cross-project coding conventions for naming, readability, immutability, and code-quality review. Use detailed frontend or backend skills for framework-specific patterns. Use when reviewing code quality or naming with no framework-specific skill that applies.4,500 instalaciones en skills.sh0