Testing Ktor application fails with "A Koin Application has already been started"
See original GitHub issueI am trying to unit test a ktor application powered by koin, described as follows:
- The
gradle.properties
:
ktor_version=1.2.2
kotlin_version=1.3.40
logback_version=1.2.1
- The
build.gradle
’s dependencies:
dependencies {
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version")
compile("io.ktor:ktor-server-netty:$ktor_version")
compile("ch.qos.logback:logback-classic:$logback_version")
compile("org.koin:koin-ktor:2.0.1")
testCompile("io.ktor:ktor-server-tests:$ktor_version")
testCompile("org.koin:koin-test:0.9.3")
}
- The
resources/application.conf
:
ktor {
deployment {
port = 8080
}
application {
modules = [com.example.MainApplicationKt.main]
}
}
- The
com.example.MainApplication.kt
:
package com.example
// imports...
interface HelloController {
suspend fun onGetHello(call: ApplicationCall)
}
class DefaultHelloController() : HelloController {
override suspend fun onGetHello(call: ApplicationCall) {
call.respondText("Hello World!")
}
}
fun main(args: Array<String>) {
embeddedServer(Netty, commandLineEnvironment(args)).start()
}
fun Application.main() {
install(DefaultHeaders)
install(CallLogging)
install(org.koin.ktor.ext.Koin) {
modules(helloModule)
}
val helloController: HelloController by inject()
routing {
get("/hello") {
helloController.onGetHello(call)
}
}
}
- and finally the
MainApplicationTest.kt
:
class MainApplicationTest {
private object MockHelloController : HelloController {
override suspend fun onGetHello(call: ApplicationCall) {
call.respondText("Mocked Hello World!")
}
}
@Before
fun setup() {
val mockHelloModule = module {
single<HelloController> { MockHelloController }
}
startKoin {
listOf(mockHelloModule)
}
}
@After
fun teardown() {
stopKoin()
}
@Test
fun testRequestsOK() = withTestApplication(Application::main) {
with(handleRequest(HttpMethod.Get, "/hello")) {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals("Mocked Hello World!", response.content)
}
}
}
When running the unit test, I get the following exception:
org.koin.core.error.KoinAppAlreadyStartedException: A Koin Application has already been started
What is the proper way to setup my unit tests?
Thanks in advance, Regards, Romain
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
A Koin Application has already been started - ...
Implementing the abstract AutoCloseKoinTest class will automatically stop Koin after each test. Here's an example with Robolectric:
Read more >Injecting in Tests
You need to Register the KoinTestExtension and provide your module configuration. After this is done you can either get or inject your components...
Read more >Testing
Ktor provides a special testing engine that doesn't create a web server, doesn't bind to sockets, and doesn't make any real HTTP requests....
Read more >Error with Koin DI in Ktor version 1.6.6+
When adding modules for dependency injection with Koin (using latest version 3.1.4) there is a weird bug in versions 1.6.6+. Here's my repo....
Read more >Now I m getting The test application has already been built
The test application has already been built. Make sure you configure the application before accessing the client for the first time. ... I...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Oops, that was easier than I thought. Just add
stopKoin()
insideI’m facing similar problem with robolectric. See this issue https://github.com/robolectric/robolectric/issues/3108
I think it’s a problem Koin is having some static variables remembering previous runs (tests). This way the tests are not isolated and something can go wrong…