Skip to content

7. Testing y calidad

Arturo Lopez edited this page Apr 8, 2026 · 2 revisions

Testing y Calidad

Pirámide:

  • Unit tests (rápidos, sin Spring): dominio y services instanciados directamente con MockK.
  • Integration tests de controlador (@WebMvcTest + MockMvc): solo carga la capa web.
  • Integration tests de repositorio (@DataJpaTest): verifica queries personalizadas contra H2.
  • Integration tests completos (Testcontainers + PostgreSQL real): detecta bugs que H2 no detectaría.
  • E2E (@SpringBootTest + TestRestTemplate): el sistema completo.

Comandos:

./gradlew test
./gradlew test --tests "PingServiceTest"
./gradlew clean test                   # limpia y ejecuta todo
./gradlew ktlintFormat                 # formatea código Kotlin

Patrones:

  • Given-When-Then.
  • Test data builders.
  • Tests deterministas (reloj inyectado si hay timestamps).
  • Cobertura de reglas de negocio, no de anotaciones.
  • Cobertura mínima: 85% con JaCoCo (señal de alerta, no número sagrado).

Estructura de tests:

src/test/kotlin/com/lgzarturo/springbootcourse/
├── config/
│   └── TestcontainersConfiguration.kt
├── common/
│   └── MockkTestConfig.kt
├── features/
│   ├── hotels/
│   │   ├── HotelControllerTest.kt      ← @WebMvcTest
│   │   ├── HotelServiceTest.kt         ← unit test con MockK
│   │   └── HotelRepositoryIntegrationTest.kt  ← @DataJpaTest
│   ├── ping/
│   │   ├── PingControllerTest.kt
│   │   └── PingServiceTest.kt
│   └── users/
│       └── CreateUserServiceTest.kt
├── BaseIntegrationTest.kt              ← Testcontainers base
└── SpringbootCourseApplicationTests.kt

Ejemplo de unit test de dominio (sin Spring):

class PingServiceTest {
    private val service = PingService()

    @Test
    fun `should return pong`() {
        val result = service.getPing()
        assertEquals("pong", result.message)
    }
}

Tests de seguridad:

Usa @WithMockUser para simular autenticación en tests de controlador:

@Test
@WithMockUser(roles = ["TRAINER"])
fun `trainer can view their reservation`() { ... }

Clone this wiki locally