refactor(audit): drop @DirtiesContext, add @BeforeEach, use existsByKind in wait conditions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-26 15:43:07 +02:00
parent 11d93919b2
commit 23cff1cdd7
2 changed files with 10 additions and 5 deletions

View File

@@ -5,4 +5,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
import java.util.UUID; import java.util.UUID;
public interface AuditLogRepository extends JpaRepository<AuditLog, UUID> { public interface AuditLogRepository extends JpaRepository<AuditLog, UUID> {
boolean existsByKind(AuditKind kind);
} }

View File

@@ -1,5 +1,6 @@
package org.raddatz.familienarchiv.audit; package org.raddatz.familienarchiv.audit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.PostgresContainerConfig; import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.raddatz.familienarchiv.dto.CreateUserRequest; import org.raddatz.familienarchiv.dto.CreateUserRequest;
@@ -9,7 +10,6 @@ import org.raddatz.familienarchiv.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
@@ -25,7 +25,6 @@ import static org.awaitility.Awaitility.await;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("test") @ActiveProfiles("test")
@Import(PostgresContainerConfig.class) @Import(PostgresContainerConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class UserManagementAuditIntegrationTest { class UserManagementAuditIntegrationTest {
@MockitoBean S3Client s3Client; @MockitoBean S3Client s3Client;
@@ -35,6 +34,11 @@ class UserManagementAuditIntegrationTest {
@Autowired AuditLogQueryService auditLogQueryService; @Autowired AuditLogQueryService auditLogQueryService;
@Autowired TransactionTemplate transactionTemplate; @Autowired TransactionTemplate transactionTemplate;
@BeforeEach
void clearAuditLog() {
transactionTemplate.execute(status -> { auditLogRepository.deleteAll(); return null; });
}
@Test @Test
void createAndDeleteUser_producesOrderedAuditEntries() { void createAndDeleteUser_producesOrderedAuditEntries() {
// Create the actor (admin) user directly — bypasses audit logging so no FK issue // Create the actor (admin) user directly — bypasses audit logging so no FK issue
@@ -46,7 +50,7 @@ class UserManagementAuditIntegrationTest {
UUID actorId = actor.getId(); UUID actorId = actor.getId();
// The admin creation is logged with null actorId — clear to start with a clean slate // The admin creation is logged with null actorId — clear to start with a clean slate
await().atMost(5, SECONDS).until(() -> auditLogRepository.count() > 0); await().atMost(5, SECONDS).until(() -> auditLogRepository.existsByKind(AuditKind.USER_CREATED));
transactionTemplate.execute(status -> { auditLogRepository.deleteAll(); return null; }); transactionTemplate.execute(status -> { auditLogRepository.deleteAll(); return null; });
// Create the target user — should emit USER_CREATED // Create the target user — should emit USER_CREATED
@@ -57,7 +61,7 @@ class UserManagementAuditIntegrationTest {
userService.createUserOrUpdate(actorId, req); userService.createUserOrUpdate(actorId, req);
return null; return null;
}); });
await().atMost(5, SECONDS).until(() -> auditLogRepository.count() > 0); await().atMost(5, SECONDS).until(() -> auditLogRepository.existsByKind(AuditKind.USER_CREATED));
// Delete the target user — should emit USER_DELETED // Delete the target user — should emit USER_DELETED
AppUser created = userRepository.findByEmail("audit-test@example.com").orElseThrow(); AppUser created = userRepository.findByEmail("audit-test@example.com").orElseThrow();
@@ -65,7 +69,7 @@ class UserManagementAuditIntegrationTest {
userService.deleteUser(actorId, created.getId()); userService.deleteUser(actorId, created.getId());
return null; return null;
}); });
await().atMost(5, SECONDS).until(() -> auditLogRepository.count() >= 2); await().atMost(5, SECONDS).until(() -> auditLogRepository.existsByKind(AuditKind.USER_DELETED));
List<AuditLog> events = auditLogQueryService.findRecentUserManagementEvents(10); List<AuditLog> events = auditLogQueryService.findRecentUserManagementEvents(10);
assertThat(events).hasSize(2); assertThat(events).hasSize(2);