From 6c8accb9b61f58a027013262b83de89ddceb3732 Mon Sep 17 00:00:00 2001 From: StefanMoCoAt Date: Sun, 1 Feb 2026 17:55:41 +0100 Subject: [PATCH] chore(backend): add integration test for PingRepository with Testcontainers setup - Implemented a minimal integration test to validate persistence layer functionality. - Configured PostgreSQL Testcontainer and Flyway migrations for testing. - Added `TestPersistenceConfig` to isolate testing setup and avoid loading unnecessary components. - Updated build script to include Testcontainers dependencies. --- .../ping/ping-service/build.gradle.kts | 1 + .../persistence/PingRepositoryTest.kt | 88 +++++++++++++++++++ .../persistence/TestPersistenceConfig.kt | 16 ++++ 3 files changed, 105 insertions(+) create mode 100644 backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/PingRepositoryTest.kt create mode 100644 backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/TestPersistenceConfig.kt diff --git a/backend/services/ping/ping-service/build.gradle.kts b/backend/services/ping/ping-service/build.gradle.kts index 5f831c02..183206b4 100644 --- a/backend/services/ping/ping-service/build.gradle.kts +++ b/backend/services/ping/ping-service/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { // === Testing === testImplementation(libs.bundles.testing.jvm) + testImplementation(libs.bundles.testcontainers) // WICHTIG: Testcontainer Bundle hinzugefügt testImplementation(libs.spring.boot.starter.test) testImplementation(libs.spring.security.test) } diff --git a/backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/PingRepositoryTest.kt b/backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/PingRepositoryTest.kt new file mode 100644 index 00000000..83ee935d --- /dev/null +++ b/backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/PingRepositoryTest.kt @@ -0,0 +1,88 @@ +package at.mocode.ping.infrastructure.persistence + +import at.mocode.ping.domain.Ping +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.context.annotation.Import +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import org.testcontainers.containers.PostgreSQLContainer +import org.testcontainers.junit.jupiter.Container +import org.testcontainers.junit.jupiter.Testcontainers +import java.time.Instant +import kotlin.uuid.ExperimentalUuidApi +import kotlin.uuid.Uuid +import kotlin.uuid.toJavaUuid + +/** + * Minimaler Integrationstest für die Persistenz-Schicht. + * Prüft: + * 1. Startet echte Postgres DB (via Testcontainers). + * 2. Führt Flyway-Migrationen aus (Schema-Erstellung). + * 3. Speichert und lädt eine Entity (Mapping-Check). + */ +@DataJpaTest +@Testcontainers +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(classes = [TestPersistenceConfig::class]) // Nutzt isolierte Config statt Main-App +@Import(PingRepositoryAdapter::class) // Importiert den Adapter, den wir testen wollen +@ActiveProfiles("test") // WICHTIG: Lädt application-test.yaml +@OptIn(ExperimentalUuidApi::class) +class PingRepositoryTest { + + @Autowired + private lateinit var repositoryAdapter: PingRepositoryAdapter + + // Wir nutzen das Repository direkt, um zu prüfen, ob JPA funktioniert + @Autowired + private lateinit var springDataRepository: SpringDataPingRepository + + companion object { + @Container + val postgres = PostgreSQLContainer("postgres:16-alpine") + .withDatabaseName("testdb") + .withUsername("test") + .withPassword("test") + + @JvmStatic + @DynamicPropertySource + fun registerPgProperties(registry: DynamicPropertyRegistry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl) + registry.add("spring.datasource.username", postgres::getUsername) + registry.add("spring.datasource.password", postgres::getPassword) + // Wichtig: Flyway muss laufen, um Tabellen zu erstellen + registry.add("spring.flyway.enabled") { "true" } + } + } + + @Test + fun `should save and load ping entity`() { + // Given + val pingId = Uuid.generateV7() + val ping = Ping( + id = pingId, + message = "Integration Test Ping", + timestamp = Instant.now() + ) + + // When + repositoryAdapter.save(ping) + + // Then (via Adapter) + val loadedPing = repositoryAdapter.findById(pingId) + assertThat(loadedPing).isNotNull + assertThat(loadedPing?.message).isEqualTo("Integration Test Ping") + assertThat(loadedPing?.id).isEqualTo(pingId) + + // Then (Direct DB Check via Spring Data) + // Fix: Use toJavaUuid() instead of UUID.fromString(pingId.toString()) + val entity = springDataRepository.findById(pingId.toJavaUuid()) + assertThat(entity).isPresent + assertThat(entity.get().message).isEqualTo("Integration Test Ping") + } +} diff --git a/backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/TestPersistenceConfig.kt b/backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/TestPersistenceConfig.kt new file mode 100644 index 00000000..af4a68cb --- /dev/null +++ b/backend/services/ping/ping-service/src/test/kotlin/at/mocode/ping/infrastructure/persistence/TestPersistenceConfig.kt @@ -0,0 +1,16 @@ +package at.mocode.ping.infrastructure.persistence + +import org.springframework.boot.SpringBootConfiguration +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan + +/** + * Minimale Konfiguration für DataJpaTests. + * Verhindert, dass die echte PingServiceApplication geladen wird, + * welche einen weiten ComponentScan auslöst und damit Controller/Services lädt, + * die wir im Repository-Test nicht brauchen (und die Fehler verursachen). + */ +@SpringBootConfiguration +@EnableAutoConfiguration +@ComponentScan(basePackages = ["at.mocode.ping.infrastructure.persistence"]) +class TestPersistenceConfig