move subscribeToBus in configureGameListener function, and use it on test

This commit is contained in:
2025-03-30 03:08:36 +02:00
parent d5d6a48df3
commit 2fb4c778fd
10 changed files with 104 additions and 37 deletions

View File

@@ -5,10 +5,10 @@ import eventDemo.business.command.command.IWantToJoinTheGameCommand
import eventDemo.business.entity.GameId
import eventDemo.business.entity.Player
import eventDemo.business.event.projection.projectionListener.PlayerNotificationListener
import eventDemo.business.event.projection.projectionListener.ReactionListener
import eventDemo.business.notification.CommandSuccessNotification
import eventDemo.business.notification.Notification
import eventDemo.business.notification.WelcomeToTheGameNotification
import eventDemo.configuration.business.configureGameListener
import eventDemo.testKoinApplicationWithConfig
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldContain
@@ -28,13 +28,13 @@ class GameCommandHandlerTest :
test("handle a command should execute the command") {
withTimeout(1.seconds) {
testKoinApplicationWithConfig {
configureGameListener()
val commandHandler by inject<GameCommandHandler>()
val notificationListener by inject<PlayerNotificationListener>()
val gameId = GameId()
val player = Player("Tesla")
val channelCommand = Channel<GameCommand>(Channel.BUFFERED)
val channelNotification = Channel<Notification>(Channel.BUFFERED)
ReactionListener(get(), get()).init()
notificationListener.startListening(
player,
gameId,

View File

@@ -6,7 +6,7 @@ import eventDemo.business.event.GameEventHandler
import eventDemo.business.event.event.NewPlayerEvent
import eventDemo.business.event.projection.gameState.GameState
import eventDemo.business.event.projection.gameState.GameStateRepository
import eventDemo.testKoinApplicationWithConfig
import eventDemo.testApplicationWithConfig
import io.kotest.assertions.nondeterministic.eventually
import io.kotest.assertions.nondeterministic.eventuallyConfig
import io.kotest.core.spec.style.FunSpec
@@ -18,7 +18,6 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import org.koin.core.context.stopKoin
import kotlin.test.assertNotNull
import kotlin.time.Duration.Companion.seconds
@@ -30,9 +29,9 @@ class GameStateRepositoryTest :
test("GameStateRepository should build the projection when a new event occurs") {
val aggregateId = GameId()
testKoinApplicationWithConfig {
val repo = get<GameStateRepository>()
val eventHandler = get<GameEventHandler>()
testApplicationWithConfig { koin ->
val repo = koin.get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>()
eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
.also { event ->
@@ -47,15 +46,14 @@ class GameStateRepositoryTest :
}
}
}
stopKoin()
}
test("get should build the last version of the state") {
val aggregateId = GameId()
testKoinApplicationWithConfig {
val repo = get<GameStateRepository>()
val eventHandler = get<GameEventHandler>()
val projectionBus = get<GameProjectionBus>()
testApplicationWithConfig { koin ->
val repo = koin.get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>()
val projectionBus = koin.get<GameProjectionBus>()
var state: GameState? = null
projectionBus.subscribe {
@@ -88,9 +86,9 @@ class GameStateRepositoryTest :
test("getUntil should build the state until the event") {
repeat(10) {
val aggregateId = GameId()
testKoinApplicationWithConfig {
val repo = get<GameStateRepository>()
val eventHandler = get<GameEventHandler>()
testApplicationWithConfig { koin ->
val repo = koin.get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>()
val event1 =
eventHandler
@@ -117,9 +115,9 @@ class GameStateRepositoryTest :
test("getUntil should be concurrently secure") {
val aggregateId = GameId()
testKoinApplicationWithConfig {
val repo = get<GameStateRepository>()
val eventHandler = get<GameEventHandler>()
testApplicationWithConfig { koin ->
val repo = koin.get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>()
(1..10)
.map { r ->

View File

@@ -1,5 +1,6 @@
package eventDemo.business.event.projection
import eventDemo.cleanProjections
import eventDemo.configuration.serializer.UUIDSerializer
import eventDemo.libs.event.AggregateId
import eventDemo.libs.event.Event
@@ -96,6 +97,37 @@ class ProjectionSnapshotRepositoryTest :
}
}
context("getList method must be return all inserted events") {
withData(list) { (eventStore, repo) ->
val aggregateId = IdTest()
val otherAggregateId = IdTest()
val eventOther = Event2Test(value2 = "valOther", version = 1, aggregateId = otherAggregateId)
eventStore.publish(eventOther)
repo.applyAndPutToCache(eventOther)
assertNotNull(repo.getUntil(eventOther)).also {
assertNotNull(it.value) shouldBeEqual "valOther"
}
val event1 = Event1Test(value1 = "val1", version = 1, aggregateId = aggregateId)
eventStore.publish(event1)
repo.applyAndPutToCache(event1)
val event2 = Event2Test(value2 = "val2", version = 2, aggregateId = aggregateId)
eventStore.publish(event2)
repo.applyAndPutToCache(event2)
repo.getList().apply {
any { it.aggregateId == otherAggregateId } shouldBeEqual true
any { it.aggregateId == aggregateId } shouldBeEqual true
any { it.value == "val1val2" } shouldBeEqual true
any { it.value == "valOther" } shouldBeEqual true
any { it.lastEventVersion == 2 } shouldBeEqual true
any { it.lastEventVersion == 1 } shouldBeEqual true
}
}
}
context("ProjectionSnapshotRepository should be thread safe") {
continually(1.seconds) {
withData(list) { (eventStore, repo) ->
@@ -199,10 +231,12 @@ private fun getSnapshotRepoInMemoryTest(
private fun getSnapshotRepoInRedisTest(
eventStore: EventStore<TestEvents, IdTest>,
snapshotConfig: SnapshotConfig,
): ProjectionSnapshotRepository<TestEvents, ProjectionTest, IdTest> =
ProjectionSnapshotRepositoryInRedis(
): ProjectionSnapshotRepository<TestEvents, ProjectionTest, IdTest> {
val jedis = JedisPooled("redis://localhost:6379")
jedis.cleanProjections()
return ProjectionSnapshotRepositoryInRedis(
eventStore = eventStore,
jedis = JedisPooled("redis://localhost:6379"),
jedis = jedis,
initialStateBuilder = { aggregateId: IdTest -> ProjectionTest(aggregateId) },
snapshotCacheConfig = snapshotConfig,
projectionClass = ProjectionTest::class,
@@ -210,16 +244,17 @@ private fun getSnapshotRepoInRedisTest(
jsonToProjection = { Json.decodeFromString(it) },
applyToProjection = apply,
)
}
private val apply: ProjectionTest.(TestEvents) -> ProjectionTest = { event ->
this.let { projection ->
when (event) {
is Event1Test -> {
projection.copy(value = (projection.value ?: "") + event.value1)
projection.copy(value = (projection.value.orEmpty()) + event.value1)
}
is Event2Test -> {
projection.copy(value = (projection.value ?: "") + event.value2)
projection.copy(value = (projection.value.orEmpty()) + event.value2)
}
is EventXTest -> {