3.0 KiB
Test Evidence: Checkout eligibility and stable conflict outcomes
- Test type: Unit
- Requirement IDs:
ATT-007,ATT-008,ATT-010,ATT-012 - Scenario IDs:
AC-ATT-003,AC-ATT-004 - Test class/method:
com.lab.labtimesheet.feature.attendance.service.AttendanceApplicationServiceTest#rejectsCheckoutWhenInternIsNoLongerEligibleForPersistedWorkDate,#translatesConcurrentCheckInUniqueConflictToStableDuplicateRejection,#translatesConcurrentCheckoutVersionConflictToStableDuplicateRejection - Implementation commit:
4c39df70e1f901e232669e9090ff5d21393519f0
Protected behavior
Checkout revalidates active internship eligibility for the attendance row's persisted work date. A terminal Intern cannot checkout after checking in. Database uniqueness and optimistic-lock races are translated to stable duplicate punch rejection codes instead of leaking persistence exceptions.
Test method
Plain JUnit and Mockito drive the production transactional application service with a fixed Clock, attached policy, persisted row, AccountService eligibility, and repository exceptions. Account state remains behind its public service API.
Hand-derived expected result
False date-aware eligibility returns INACTIVE_INTERN before raw checkout is
saved. A check-in uniqueness race returns ALREADY_CHECKED_IN; a checkout
version race returns ALREADY_CHECKED_OUT.
RED
Command
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="$JAVA_HOME/bin:$PATH"
./mvnw -Dtest=AttendanceApplicationServiceTest#rejectsCheckoutWhenInternIsNoLongerEligibleForPersistedWorkDate test
Observed result
Expected AttendanceException(INACTIVE_INTERN) but was NullPointerException after
the service continued to save checkout without calling AccountService eligibility.
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
BUILD FAILURE
Process exited 1.
The conflict regressions were also observed RED in the combined focused run:
DataIntegrityViolationException: concurrent unique conflict
ObjectOptimisticLockingFailureException: optimistic locking failed
Both escaped AttendanceApplicationService instead of stable AttendanceException values.
GREEN
Command
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="$JAVA_HOME/bin:$PATH"
./mvnw -Dtest=AttendanceApplicationServiceTest test
Observed result
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Process exited 0.
Affected suite
Command and result
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="$JAVA_HOME/bin:$PATH"
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
./mvnw -Dtest='*Attendance*Test' test
Tests run: 32, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Process exited 0.
External-test boundaries
The account platform has no Iteration 1 terminal-state mutation API, so the completed/withdrawn state is represented through its public date-aware eligibility result. The companion PostgreSQL concurrency test proves the real unique conflict.