From 435899748213dbcd4327709d97de44689b530bcf Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 15 May 2026 10:29:35 +0200 Subject: [PATCH] perf(test): replace DirtiesContext(AFTER_EACH_TEST_METHOD) with @Transactional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 4 integration test classes were restarting the full Spring context (and a new Postgres Testcontainer, ~75s each) after every test method — 10 unnecessary container startups adding ~12 minutes to CI. Fixed by: - PersonServiceIntegrationTest, DocumentSearchPagedIntegrationTest, GeschichteServiceIntegrationTest: swap to @Transactional so each test rolls back instead of destroying the context. - AuditServiceIntegrationTest: cannot use @Transactional (logAfterCommit hooks into AFTER_COMMIT which requires a real commit); reset state with @BeforeEach deleteAll() instead. Co-Authored-By: Claude Sonnet 4.6 --- .../familienarchiv/audit/AuditServiceIntegrationTest.java | 8 ++++++-- .../document/DocumentSearchPagedIntegrationTest.java | 4 ++-- .../geschichte/GeschichteServiceIntegrationTest.java | 4 ++-- .../person/PersonServiceIntegrationTest.java | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/backend/src/test/java/org/raddatz/familienarchiv/audit/AuditServiceIntegrationTest.java b/backend/src/test/java/org/raddatz/familienarchiv/audit/AuditServiceIntegrationTest.java index b8401d18..16db59be 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/audit/AuditServiceIntegrationTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/audit/AuditServiceIntegrationTest.java @@ -1,11 +1,11 @@ package org.raddatz.familienarchiv.audit; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.raddatz.familienarchiv.PostgresContainerConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.transaction.support.TransactionTemplate; @@ -18,7 +18,6 @@ import static org.awaitility.Awaitility.await; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @ActiveProfiles("test") @Import(PostgresContainerConfig.class) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class AuditServiceIntegrationTest { @MockitoBean S3Client s3Client; @@ -26,6 +25,11 @@ class AuditServiceIntegrationTest { @Autowired AuditLogRepository auditLogRepository; @Autowired TransactionTemplate transactionTemplate; + @BeforeEach + void resetAuditLog() { + auditLogRepository.deleteAll(); + } + @Test void logAfterCommit_writes_ANNOTATION_CREATED_row_after_transaction_commits() { transactionTemplate.execute(status -> { diff --git a/backend/src/test/java/org/raddatz/familienarchiv/document/DocumentSearchPagedIntegrationTest.java b/backend/src/test/java/org/raddatz/familienarchiv/document/DocumentSearchPagedIntegrationTest.java index bdf9f810..0ba61da3 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/document/DocumentSearchPagedIntegrationTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/document/DocumentSearchPagedIntegrationTest.java @@ -12,9 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.data.domain.PageRequest; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.transaction.annotation.Transactional; import software.amazon.awssdk.services.s3.S3Client; import java.time.LocalDate; @@ -33,7 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @ActiveProfiles("test") @Import(PostgresContainerConfig.class) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +@Transactional class DocumentSearchPagedIntegrationTest { private static final int FIXTURE_SIZE = 120; diff --git a/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteServiceIntegrationTest.java b/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteServiceIntegrationTest.java index 55eaaa4c..31c73af1 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteServiceIntegrationTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteServiceIntegrationTest.java @@ -19,9 +19,9 @@ import org.springframework.context.annotation.Import; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.transaction.annotation.Transactional; import software.amazon.awssdk.services.s3.S3Client; import java.util.List; @@ -32,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @ActiveProfiles("test") @Import(PostgresContainerConfig.class) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +@Transactional class GeschichteServiceIntegrationTest { @MockitoBean diff --git a/backend/src/test/java/org/raddatz/familienarchiv/person/PersonServiceIntegrationTest.java b/backend/src/test/java/org/raddatz/familienarchiv/person/PersonServiceIntegrationTest.java index 02cc7aa4..e8d5ed97 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/person/PersonServiceIntegrationTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/person/PersonServiceIntegrationTest.java @@ -8,9 +8,9 @@ import org.raddatz.familienarchiv.person.PersonRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.transaction.annotation.Transactional; import software.amazon.awssdk.services.s3.S3Client; import static org.assertj.core.api.Assertions.assertThat; @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @ActiveProfiles("test") @Import(PostgresContainerConfig.class) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +@Transactional class PersonServiceIntegrationTest { @MockitoBean S3Client s3Client;