I'm looking to properly test a Ktor application, which uses Koin and is specifically not using the embeddedServer method of creating the app. All solutions that I have found were either outdated or were using the embedded server. Here is a simplified version of my code:
Main.kt
fun main(args: Array<String>): Unit = EngineMain.main(args)
fun Application.koinModule() {
install(Koin) {
modules(myModule)
}
}
fun Application.doOtherStuff() {
val someSingleton by inject<SomeSingleton>()
(...)
}
application.yaml:
ktor:
deployment:
port: 8080
application:
modules:
- MainKt.koinModule
- MainKt.doOtherStuff
My current solution does somewhat work, but feels hacky and spams KoinNotStartedException
in the console:
Test.kt:
class MyTest : KoinTest {
@AfterEach
fun cleanup() {
stopKoin()
}
@Test
fun `mock koin module`() = testApplication {
startKoin {
modules(
myModule,
myMockModule, // override module with mocks
)
}
environment {
config = ApplicationConfig("application-test.yaml")
}
(...) // test code
}
}
application-test.yaml
ktor:
deployment:
port: 8080
application:
modules: # same as application.yaml, but without koin module
- MainKt.doOtherStuff
If there is an intended and more importantly documented way of testing Ktor with Koin, feel free to link it. Thank you!
I think your problem is that you are starting koin inside testApplication {}
which already expects koin context to be up. To get ahead you should use KoinTestRule
for junit4 or KoinTestExtension
for junit5.
class MyTest : KoinTest {
companion object {
@JvmField
@RegisterExtension
val koinTestExtension = KoinTestExtension.create {
modules(myModule, myMockModule)
}
}
@Test
fun `test`() = testApplication {
...
}
}
More detailes in koin docs https://insert-koin.io/docs/reference/koin-test/testing