test: limit log level in some tests

This commit is contained in:
2025-04-12 05:31:24 +02:00
parent f0308c7d3e
commit ec3ccafc4d
2 changed files with 136 additions and 81 deletions

View File

@@ -0,0 +1,32 @@
package eventDemo
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import org.slf4j.LoggerFactory
inline fun <T> withLogLevel(
vararg logs: Pair<String, Level>,
block: () -> T,
): T {
val originalLevels =
run {
logs.toList().associate { (log, level) ->
val logger = LoggerFactory.getLogger(log) as Logger
log to logger.level
}
}
logs.forEach { (log, level) ->
val logger = LoggerFactory.getLogger(log) as Logger
logger.level = level
}
val output = block()
logs.forEach { (log, level) ->
val logger = LoggerFactory.getLogger(log) as Logger
logger.level = originalLevels[log]
}
return output
}

View File

@@ -1,6 +1,10 @@
package eventDemo.business.event.projection package eventDemo.business.event.projection
import ch.qos.logback.classic.Level
import com.rabbitmq.client.impl.ForgivingExceptionHandler
import com.zaxxer.hikari.pool.ProxyConnection
import eventDemo.Tag import eventDemo.Tag
import eventDemo.business.command.GameCommandHandler
import eventDemo.business.entity.GameId import eventDemo.business.entity.GameId
import eventDemo.business.entity.Player import eventDemo.business.entity.Player
import eventDemo.business.event.GameEventHandler import eventDemo.business.event.GameEventHandler
@@ -8,6 +12,7 @@ import eventDemo.business.event.event.NewPlayerEvent
import eventDemo.business.event.projection.gameState.GameState import eventDemo.business.event.projection.gameState.GameState
import eventDemo.business.event.projection.gameState.GameStateRepository import eventDemo.business.event.projection.gameState.GameStateRepository
import eventDemo.testKoinApplicationWithConfig import eventDemo.testKoinApplicationWithConfig
import eventDemo.withLogLevel
import io.kotest.assertions.nondeterministic.eventually import io.kotest.assertions.nondeterministic.eventually
import io.kotest.assertions.nondeterministic.eventuallyConfig import io.kotest.assertions.nondeterministic.eventuallyConfig
import io.kotest.common.KotestInternal import io.kotest.common.KotestInternal
@@ -19,6 +24,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.joinAll import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.slf4j.Logger
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -52,106 +58,123 @@ class GameStateRepositoryTest :
} }
test("get should build the last version of the state") { test("get should build the last version of the state") {
val aggregateId = GameId() withLogLevel(
testKoinApplicationWithConfig { GameCommandHandler::class.java.name to Level.ERROR,
val repo = get<GameStateRepository>() ForgivingExceptionHandler::class.java.name to Level.OFF,
val eventHandler = get<GameEventHandler>() ) {
val projectionBus = get<GameProjectionBus>()
var state: GameState? = null
projectionBus.subscribe {
repo.getLast(aggregateId).also {
state = it
}
}
eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
.also {
eventually(1.seconds) {
assertNotNull(state).players.isNotEmpty() shouldBeEqual true
assertNotNull(state).players shouldBeEqual setOf(player1)
}
}
eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player2, version = it) }
.also {
eventually(1.seconds) {
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() val aggregateId = GameId()
testKoinApplicationWithConfig { testKoinApplicationWithConfig {
val repo = get<GameStateRepository>() val repo = get<GameStateRepository>()
val eventHandler = get<GameEventHandler>() val eventHandler = get<GameEventHandler>()
val projectionBus = get<GameProjectionBus>()
var state: GameState? = null
projectionBus.subscribe {
repo.getLast(aggregateId).also {
state = it
}
}
eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
.also {
eventually(1.seconds) {
assertNotNull(state).players.isNotEmpty() shouldBeEqual true
assertNotNull(state).players shouldBeEqual setOf(player1)
}
}
eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player2, version = it) }
.also {
eventually(1.seconds) {
assertNotNull(repo.getLast(aggregateId)).also {
assertNotNull(it.players) shouldBeEqual setOf(player1, player2)
}
}
}
}
}
}
test("getUntil should build the state until the event") {
withLogLevel(
GameCommandHandler::class.java.name to Level.ERROR,
ForgivingExceptionHandler::class.java.name to Level.OFF,
ProxyConnection::class.java.name to Level.OFF,
Logger.ROOT_LOGGER_NAME to Level.INFO,
) {
repeat(10) {
val aggregateId = GameId()
testKoinApplicationWithConfig {
val repo = get<GameStateRepository>()
val eventHandler = get<GameEventHandler>()
val event1 =
eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
.also { event1 ->
assertNotNull(repo.getUntil(event1)).also {
assertNotNull(it.players) shouldBeEqual setOf(player1)
}
}
val event1 =
eventHandler eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) } .handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player2, version = it) }
.also { event1 -> .also { event2 ->
assertNotNull(repo.getUntil(event2)).also {
assertNotNull(it.players) shouldBeEqual setOf(player1, player2)
}
assertNotNull(repo.getUntil(event1)).also { assertNotNull(repo.getUntil(event1)).also {
assertNotNull(it.players) shouldBeEqual setOf(player1) assertNotNull(it.players) shouldBeEqual setOf(player1)
} }
} }
}
eventHandler
.handle(aggregateId) { 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").config(tags = setOf(Tag.Concurrence)) { test("getUntil should be concurrently secure").config(tags = setOf(Tag.Concurrence)) {
val aggregateId = GameId() withLogLevel(
testKoinApplicationWithConfig { Logger.ROOT_LOGGER_NAME to Level.ERROR,
val repo = get<GameStateRepository>() ForgivingExceptionHandler::class.java.name to Level.OFF,
val eventHandler = get<GameEventHandler>() ) {
val aggregateId = GameId()
testKoinApplicationWithConfig {
val repo = get<GameStateRepository>()
val eventHandler = get<GameEventHandler>()
(1..10) (1..10)
.map { r -> .map { r ->
GlobalScope GlobalScope
.launch { .launch {
repeat(100) { r2 -> repeat(20) { r2 ->
val playerX = Player("player$r$r2") val playerX = Player("player$r$r2")
eventHandler eventHandler
.handle(aggregateId) { .handle(aggregateId) {
NewPlayerEvent( NewPlayerEvent(
aggregateId = aggregateId, aggregateId = aggregateId,
player = playerX, player = playerX,
version = it, version = it,
) )
} }
}
} }
} }.joinAll()
}.joinAll()
eventually( eventually(
eventuallyConfig { eventuallyConfig {
duration = 10.seconds duration = 10.seconds
interval = 1.seconds interval = 1.seconds
includeFirst = false includeFirst = false
}, },
) { ) {
repo.getLast(aggregateId).run { repo.getLast(aggregateId).run {
lastEventVersion shouldBeEqual 1000 lastEventVersion shouldBeEqual 200
players shouldHaveSize 1000 players shouldHaveSize 200
}
repo.count(aggregateId) shouldBe 39
} }
repo.count(aggregateId) shouldBe 119
} }
} }
} }