fix testApplicationWithConfig

This commit is contained in:
2025-04-05 04:44:48 +02:00
parent e1529ee52c
commit fd954e631d
7 changed files with 60 additions and 56 deletions

View File

@@ -5,7 +5,6 @@ import eventDemo.business.entity.Deck
import eventDemo.configuration.business.configureGameListener import eventDemo.configuration.business.configureGameListener
import eventDemo.configuration.injection.appKoinModule import eventDemo.configuration.injection.appKoinModule
import eventDemo.configuration.ktor.configuration import eventDemo.configuration.ktor.configuration
import io.kotest.engine.runBlocking
import io.ktor.server.config.ApplicationConfig import io.ktor.server.config.ApplicationConfig
import io.ktor.server.testing.ApplicationTestBuilder import io.ktor.server.testing.ApplicationTestBuilder
import io.ktor.server.testing.testApplication import io.ktor.server.testing.testApplication
@@ -13,6 +12,7 @@ import io.ktor.utils.io.KtorDsl
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.module.KoinApplicationDslMarker import org.koin.core.module.KoinApplicationDslMarker
import org.koin.dsl.koinApplication import org.koin.dsl.koinApplication
import org.koin.ktor.ext.getKoin
import redis.clients.jedis.UnifiedJedis import redis.clients.jedis.UnifiedJedis
import javax.sql.DataSource import javax.sql.DataSource
@@ -24,22 +24,31 @@ fun Deck.allCards(): Set<Card> =
@KoinApplicationDslMarker @KoinApplicationDslMarker
suspend fun <T> testKoinApplicationWithConfig(block: suspend Koin.() -> T): T = suspend fun <T> testKoinApplicationWithConfig(block: suspend Koin.() -> T): T =
koinApplication { modules(appKoinModule(ApplicationConfig("application.conf").configuration())) }.koin.block() koinApplication { modules(appKoinModule(ApplicationConfig("application.conf").configuration())) }
.koin
.apply {
cleanDataTest()
configureGameListener()
}.block()
@KtorDsl @KtorDsl
suspend fun testApplicationWithConfig(block: suspend ApplicationTestBuilder.(koin: Koin) -> Unit) { fun testApplicationWithConfig(
configBuilder: Koin.() -> Unit = {},
block: suspend ApplicationTestBuilder.() -> Unit,
) {
testApplication { testApplication {
val conf = ApplicationConfig("application.conf") val conf = ApplicationConfig("application.conf")
environment { environment {
config = conf config = conf
} }
val koin = koinApplication { modules(appKoinModule(conf.configuration())) }.koin application {
koin.cleanDataTest() val koin = getKoin()
koin.configureGameListener() koin.cleanDataTest()
runBlocking { koin.configureGameListener()
block(koin) configBuilder(koin)
} }
block()
} }
} }

View File

@@ -44,15 +44,18 @@ class GameListRouteTest :
} }
test("/games return a game with status OPENING") { test("/games return a game with status OPENING") {
testApplicationWithConfig { koin -> val gameId = GameId()
val gameId = GameId() val player1 = Player(name = "Nikola")
val player1 = Player(name = "Nikola") testApplicationWithConfig(
{
val eventHandler = koin.get<GameEventHandler>() runBlocking {
runBlocking { get<GameEventHandler>()
eventHandler.handle(gameId) { NewPlayerEvent(gameId, player1, it) } .handle(gameId) {
} NewPlayerEvent(gameId, player1, it)
}
}
},
) {
// Wait until the projection is created // Wait until the projection is created
eventually(3.seconds) { eventually(3.seconds) {
httpClient() httpClient()
@@ -73,11 +76,11 @@ class GameListRouteTest :
} }
test("/games return a game with status IS_STARTED") { test("/games return a game with status IS_STARTED") {
testApplicationWithConfig { koin -> val gameId = GameId()
val gameId = GameId() val player1 = Player(name = "Nikola")
val player1 = Player(name = "Nikola") val player2 = Player(name = "Einstein")
val player2 = Player(name = "Einstein") testApplicationWithConfig({
val eventHandler = koin.get<GameEventHandler>() val eventHandler = get<GameEventHandler>()
runBlocking { runBlocking {
eventHandler.handle(gameId) { NewPlayerEvent(gameId, player1, it) } eventHandler.handle(gameId) { NewPlayerEvent(gameId, player1, it) }
eventHandler.handle(gameId) { NewPlayerEvent(gameId, player2, it) } eventHandler.handle(gameId) { NewPlayerEvent(gameId, player2, it) }
@@ -92,7 +95,7 @@ class GameListRouteTest :
) )
} }
} }
}) {
httpClient() httpClient()
.get("/games") { .get("/games") {
withAuth(player1) withAuth(player1)

View File

@@ -21,7 +21,6 @@ import eventDemo.business.notification.PlayerAsPlayACardNotification
import eventDemo.business.notification.PlayerWasReadyNotification import eventDemo.business.notification.PlayerWasReadyNotification
import eventDemo.business.notification.TheGameWasStartedNotification import eventDemo.business.notification.TheGameWasStartedNotification
import eventDemo.business.notification.WelcomeToTheGameNotification import eventDemo.business.notification.WelcomeToTheGameNotification
import eventDemo.configuration.business.configureGameListener
import eventDemo.libs.event.projection.ProjectionSnapshotRepositoryInMemory import eventDemo.libs.event.projection.ProjectionSnapshotRepositoryInMemory
import eventDemo.testKoinApplicationWithConfig import eventDemo.testKoinApplicationWithConfig
import io.kotest.assertions.nondeterministic.until import io.kotest.assertions.nondeterministic.until
@@ -177,7 +176,6 @@ class GameSimulationTest :
val commandHandler by inject<GameCommandHandler>() val commandHandler by inject<GameCommandHandler>()
val eventStore by inject<GameEventStore>() val eventStore by inject<GameEventStore>()
val playerNotificationListener by inject<PlayerNotificationListener>() val playerNotificationListener by inject<PlayerNotificationListener>()
configureGameListener()
playerNotificationListener.startListening(player1, gameId) { channelNotification1.trySendBlocking(it) } playerNotificationListener.startListening(player1, gameId) { channelNotification1.trySendBlocking(it) }
playerNotificationListener.startListening(player2, gameId) { channelNotification2.trySendBlocking(it) } playerNotificationListener.startListening(player2, gameId) { channelNotification2.trySendBlocking(it) }

View File

@@ -48,14 +48,13 @@ class GameStateRouteTest :
} }
test("/games/{id}/card/last") { test("/games/{id}/card/last") {
testApplicationWithConfig { koin -> val gameId = GameId()
val gameId = GameId() val player1 = Player(name = "Nikola")
val player1 = Player(name = "Nikola") val player2 = Player(name = "Einstein")
val player2 = Player(name = "Einstein") var lastPlayedCard: Card? = null
var lastPlayedCard: Card? = null testApplicationWithConfig({
val eventHandler = get<GameEventHandler>()
val eventHandler = koin.get<GameEventHandler>() val stateRepo = get<GameStateRepository>()
val stateRepo = koin.get<GameStateRepository>()
runBlocking { runBlocking {
eventHandler.handle(gameId) { NewPlayerEvent(gameId, player1, it) } eventHandler.handle(gameId) { NewPlayerEvent(gameId, player1, it) }
@@ -89,7 +88,7 @@ class GameStateRouteTest :
} }
delay(100) delay(100)
} }
}) {
httpClient() httpClient()
.get("/games/$gameId/card/last") { .get("/games/$gameId/card/last") {
withAuth(player1) withAuth(player1)

View File

@@ -8,7 +8,6 @@ import eventDemo.business.event.projection.projectionListener.PlayerNotification
import eventDemo.business.notification.CommandSuccessNotification import eventDemo.business.notification.CommandSuccessNotification
import eventDemo.business.notification.Notification import eventDemo.business.notification.Notification
import eventDemo.business.notification.WelcomeToTheGameNotification import eventDemo.business.notification.WelcomeToTheGameNotification
import eventDemo.configuration.business.configureGameListener
import eventDemo.testKoinApplicationWithConfig import eventDemo.testKoinApplicationWithConfig
import io.kotest.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.collections.shouldContain
@@ -26,11 +25,10 @@ import kotlin.time.Duration.Companion.seconds
class GameCommandHandlerTest : class GameCommandHandlerTest :
FunSpec({ FunSpec({
test("handle a command should execute the command") { test("handle a command should execute the command") {
withTimeout(1.seconds) { withTimeout(5.seconds) {
testKoinApplicationWithConfig { testKoinApplicationWithConfig {
configureGameListener() val commandHandler = get<GameCommandHandler>()
val commandHandler by inject<GameCommandHandler>() val notificationListener = get<PlayerNotificationListener>()
val notificationListener by inject<PlayerNotificationListener>()
val gameId = GameId() val gameId = GameId()
val player = Player("Tesla") val player = Player("Tesla")
val channelCommand = Channel<GameCommand>(Channel.BUFFERED) val channelCommand = Channel<GameCommand>(Channel.BUFFERED)

View File

@@ -6,7 +6,7 @@ import eventDemo.business.event.GameEventHandler
import eventDemo.business.event.event.NewPlayerEvent 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.testApplicationWithConfig import eventDemo.testKoinApplicationWithConfig
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.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
@@ -29,9 +29,9 @@ class GameStateRepositoryTest :
test("GameStateRepository should build the projection when a new event occurs") { test("GameStateRepository should build the projection when a new event occurs") {
val aggregateId = GameId() val aggregateId = GameId()
testApplicationWithConfig { koin -> testKoinApplicationWithConfig {
val repo = koin.get<GameStateRepository>() val repo = get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>() val eventHandler = get<GameEventHandler>()
eventHandler eventHandler
.handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) } .handle(aggregateId) { NewPlayerEvent(aggregateId = aggregateId, player = player1, version = it) }
.also { event -> .also { event ->
@@ -50,10 +50,10 @@ 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() val aggregateId = GameId()
testApplicationWithConfig { koin -> testKoinApplicationWithConfig {
val repo = koin.get<GameStateRepository>() val repo = get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>() val eventHandler = get<GameEventHandler>()
val projectionBus = koin.get<GameProjectionBus>() val projectionBus = get<GameProjectionBus>()
var state: GameState? = null var state: GameState? = null
projectionBus.subscribe { projectionBus.subscribe {
@@ -86,9 +86,9 @@ class GameStateRepositoryTest :
test("getUntil should build the state until the event") { test("getUntil should build the state until the event") {
repeat(10) { repeat(10) {
val aggregateId = GameId() val aggregateId = GameId()
testApplicationWithConfig { koin -> testKoinApplicationWithConfig {
val repo = koin.get<GameStateRepository>() val repo = get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>() val eventHandler = get<GameEventHandler>()
val event1 = val event1 =
eventHandler eventHandler
@@ -115,9 +115,9 @@ class GameStateRepositoryTest :
test("getUntil should be concurrently secure") { test("getUntil should be concurrently secure") {
val aggregateId = GameId() val aggregateId = GameId()
testApplicationWithConfig { koin -> testKoinApplicationWithConfig {
val repo = koin.get<GameStateRepository>() val repo = get<GameStateRepository>()
val eventHandler = koin.get<GameEventHandler>() val eventHandler = get<GameEventHandler>()
(1..10) (1..10)
.map { r -> .map { r ->

View File

@@ -1,6 +1,5 @@
package eventDemo.libs.event package eventDemo.libs.event
import eventDemo.cleanEventSource
import eventDemo.testKoinApplicationWithConfig import eventDemo.testKoinApplicationWithConfig
import io.kotest.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
import io.kotest.datatest.withData import io.kotest.datatest.withData
@@ -13,7 +12,6 @@ import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.junit.jupiter.api.assertNull import org.junit.jupiter.api.assertNull
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import javax.sql.DataSource
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
@DelicateCoroutinesApi @DelicateCoroutinesApi
@@ -29,7 +27,6 @@ class EventStreamTest :
suspend fun eventStreams(): List<EventStream<EventXTest, IdTest>> = suspend fun eventStreams(): List<EventStream<EventXTest, IdTest>> =
testKoinApplicationWithConfig { testKoinApplicationWithConfig {
get<DataSource>().cleanEventSource()
listOf( listOf(
EventStreamInMemory(IdTest()), EventStreamInMemory(IdTest()),
EventStreamInPostgresql( EventStreamInPostgresql(