extract projection snapshot logic
implement GameStateRepositoryTest
add lambda to the GameEventHandler.handle{} to set the version
add VersionBuilder
add version to the events
add creation date to the events
rename gameId to aggregateId
add EventHandler interface
This commit is contained in:
@@ -1,16 +1,128 @@
|
||||
package eventDemo.app.event.projection
|
||||
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.event.NewPlayerEvent
|
||||
import eventDemo.configuration.appKoinModule
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.collections.shouldHaveSize
|
||||
import io.kotest.matchers.equals.shouldBeEqual
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.joinAll
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.context.stopKoin
|
||||
import org.koin.dsl.koinApplication
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
class GameStateRepositoryTest :
|
||||
FunSpec({
|
||||
xtest("GameStateRepository should build the projection when a new event occurs") { }
|
||||
val player1 = Player("Tesla")
|
||||
val player2 = Player(name = "Einstein")
|
||||
|
||||
xtest("get should build the last version of the state") { }
|
||||
xtest("get should be concurrently secure") { }
|
||||
xtest("get should be concurrently secure") { }
|
||||
test("GameStateRepository should build the projection when a new event occurs") {
|
||||
val aggregateId = GameId()
|
||||
koinApplication { modules(appKoinModule) }.koin.apply {
|
||||
val repo = get<GameStateRepository>()
|
||||
val eventHandler = get<GameEventHandler>()
|
||||
eventHandler
|
||||
.handle { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
|
||||
.also { event ->
|
||||
assertNotNull(repo.getUntil(event)).also {
|
||||
assertNotNull(it.players) shouldBeEqual setOf(player1)
|
||||
}
|
||||
assertNotNull(repo.getLast(aggregateId)).also {
|
||||
assertNotNull(it.players) shouldBeEqual setOf(player1)
|
||||
}
|
||||
}
|
||||
}
|
||||
stopKoin()
|
||||
}
|
||||
|
||||
xtest("getUntil should build the state until the event") { }
|
||||
xtest("call getUntil twice should get the state from the cache") { }
|
||||
xtest("getUntil should be concurrently secure") { }
|
||||
test("get should build the last version of the state") {
|
||||
val aggregateId = GameId()
|
||||
koinApplication { modules(appKoinModule) }.koin.apply {
|
||||
val repo = get<GameStateRepository>()
|
||||
val eventHandler = get<GameEventHandler>()
|
||||
|
||||
eventHandler
|
||||
.handle { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
|
||||
.also {
|
||||
assertNotNull(repo.getLast(aggregateId)).also {
|
||||
assertNotNull(it.players) shouldBeEqual setOf(player1)
|
||||
}
|
||||
}
|
||||
|
||||
eventHandler
|
||||
.handle { NewPlayerEvent(aggregateId = aggregateId, player = player2, version = it) }
|
||||
.also {
|
||||
assertNotNull(repo.getLast(aggregateId)).also {
|
||||
assertNotNull(it.players) shouldBeEqual setOf(player1, player2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test("getUntil should build the state until the event") {
|
||||
repeat(10) {
|
||||
val aggregateId = GameId()
|
||||
koinApplication { modules(appKoinModule) }.koin.apply {
|
||||
val repo = get<GameStateRepository>()
|
||||
val eventHandler = get<GameEventHandler>()
|
||||
|
||||
val event1 =
|
||||
eventHandler
|
||||
.handle { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
|
||||
.also { event1 ->
|
||||
assertNotNull(repo.getUntil(event1)).also {
|
||||
assertNotNull(it.players) shouldBeEqual setOf(player1)
|
||||
}
|
||||
}
|
||||
|
||||
eventHandler
|
||||
.handle { NewPlayerEvent(aggregateId = aggregateId, player = player2, version = it) }
|
||||
.also { event2 ->
|
||||
assertNotNull(repo.getUntil(event2)).also {
|
||||
assertNotNull(it.players) shouldBeEqual setOf(player1, player2)
|
||||
}
|
||||
assertNotNull(repo.getUntil(event1)).also {
|
||||
assertNotNull(it.players) shouldBeEqual setOf(player1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test("getUntil should be concurrently secure") {
|
||||
val aggregateId = GameId()
|
||||
koinApplication { modules(appKoinModule) }.koin.apply {
|
||||
val repo = get<GameStateRepository>()
|
||||
val eventHandler = get<GameEventHandler>()
|
||||
|
||||
(1..10)
|
||||
.map { r ->
|
||||
GlobalScope
|
||||
.launch {
|
||||
repeat(100) { r2 ->
|
||||
val playerX = Player("player$r$r2")
|
||||
eventHandler
|
||||
.handle {
|
||||
NewPlayerEvent(
|
||||
aggregateId = aggregateId,
|
||||
player = playerX,
|
||||
version = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.joinAll()
|
||||
|
||||
repo.getLast(aggregateId).players shouldHaveSize 1000
|
||||
repo.getLast(aggregateId).lastEventVersion shouldBeEqual 1000
|
||||
}
|
||||
}
|
||||
|
||||
xtest("get should be concurrently secure") { }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user