test(fixtures): DeterministicHarness — event-log-in, derived-state-out builder
Provides a reusable builder that packages the event-log-in → derived-state-out pattern for deterministic tests. Implements fixed clock and deterministic event ID generation to ensure byte-identical event JSON across test runs with same payloads. Acceptance criteria met: - Two harnesses fed same payloads yield byte-identical stored event JSON - Fixed clock ensures timestamp determinism (2026-01-01T00:00:00Z) - Event IDs are deterministically generated (event-0, event-1, etc.) - Supports both givenEvents (append) and rebuild (replay via projection)
This commit is contained in:
@@ -14,5 +14,6 @@ dependencies {
|
||||
implementation(project(":core:context"))
|
||||
implementation(project(":core:kernel"))
|
||||
implementation(project(":core:validation"))
|
||||
implementation(project(":infrastructure:persistence"))
|
||||
}
|
||||
tasks.named("koverVerify").configure { enabled = false }
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.correx.testing.fixtures
|
||||
|
||||
import com.correx.core.events.events.EventMetadata
|
||||
import com.correx.core.events.events.EventPayload
|
||||
import com.correx.core.events.events.NewEvent
|
||||
import com.correx.core.events.types.EventId
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.infrastructure.persistence.InMemoryEventStore
|
||||
import com.correx.core.sessions.projections.Projection
|
||||
import com.correx.core.sessions.projections.replay.DefaultEventReplayer
|
||||
import kotlinx.datetime.Instant
|
||||
|
||||
class DeterministicHarness {
|
||||
val eventStore: InMemoryEventStore = InMemoryEventStore()
|
||||
val clock: Instant = Instant.parse("2026-01-01T00:00:00Z")
|
||||
|
||||
private var eventCounter = 0
|
||||
|
||||
suspend fun givenEvents(sessionId: SessionId, vararg payloads: EventPayload) {
|
||||
val events = payloads.map { payload ->
|
||||
val eventId = EventId("event-${eventCounter++}")
|
||||
NewEvent(
|
||||
metadata = EventMetadata(
|
||||
eventId = eventId,
|
||||
sessionId = sessionId,
|
||||
timestamp = clock,
|
||||
schemaVersion = 1,
|
||||
causationId = null,
|
||||
correlationId = null
|
||||
),
|
||||
payload = payload
|
||||
)
|
||||
}
|
||||
eventStore.appendAll(events)
|
||||
}
|
||||
|
||||
fun <S> rebuild(sessionId: SessionId, projection: Projection<S>): S {
|
||||
val replayer = DefaultEventReplayer(eventStore, projection)
|
||||
return replayer.rebuild(sessionId)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user