```class OptionGroupControllerTest : KoinTest { ...
# announcements
m
Copy code
class OptionGroupControllerTest : KoinTest {

    private val optionGroup: String = this::class.java
            .getResource("/jsons/option_group.json")
            .readText()
            .replace("\n", "")
            .replace(" ", "")

    @BeforeTest
    fun setup() {
        startKoin {
            module {
                single<OptionGroupController>()
                single<OptionGroupService>()
            }
        }
    }

    @AfterTest
    fun teardown() {
        stopKoin()
    }



    @Test
    fun `create option`() = withTestApplication(Application::routes) {
        with(handleRequest(<http://HttpMethod.Post|HttpMethod.Post>, "/optionGroup") {
            addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
            setBody(optionGroup)
        }) {
            assertEquals(HttpStatusCode.Created, response.status())
        }
    }

}
My Routes:
Copy code
fun Application.routes() {

    val controllerOptionGroup: OptionGroupController by inject()
    val controllerOption: OptionController by inject()

    routing {

        get("/") {
            call.respondText("OK")
        }

        get("/health") {
            call.respondText("OK")
        }

        route("/optionGroup") {
            post {
                try {
                    val message = call.receive<String>()
                    val messageOptionGroup: OptionGroupDTO = Mapper.read(message)
                    println("SERVER: Message from the client: $message")
                    call.respond(controllerOptionGroup.create(call, messageOptionGroup))
                } catch (ex: ItemException) {
                    call.respond(HttpStatusCode.BadRequest, mapOf("code" to ex.code, "messages" to arrayListOf(ex.message)))
                }
            }
        }
    }
}
And the exception is thrown at line:
Copy code
call.respond(controllerOptionGroup.create(call, messageOptionGroup))
This problem only gives me when running the tests. When I run the application everything works correctly. I would really appreciate if someone can give me a hand with this 🙂
n
have you tried to move the koin intialization into a
install(Koin) {}
block?
m
No, I didn't do it. And now that you mention it, it makes sense. I have no idea why I initialized Koin one way in the tests and another way in the app. I think I did it that way because they were the examples I found haha. Thank you!
I added ktor.Application to be able to initialize Koin inside an install block. But how do I use that within the test context?
Copy code
class OptionGroupControllerTest : KoinTest {

    private val optionGroup: String = this::class.java
            .getResource("/jsons/option_group.json")
            .readText()
            .replace("\n", "")
            .replace(" ", "")


    private val testModule: Module = module(override = true) {
        single { OptionGroupService() }
        single { OptionGroupController(get()) }
    }


    fun Application.koinInitialization() {
        install(Koin) {
            module { testModule }
        }
    }

    @BeforeTest
    fun setup(){

    }

    @AfterTest
    fun teardown() {
        stopKoin()
    }


    @Test
    fun `create option`() = withTestApplication(Application::routes) {
        with(handleRequest(<http://HttpMethod.Post|HttpMethod.Post>, "/optionGroup") {
            addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
            setBody(optionGroup)
        }) {
            assertEquals(HttpStatusCode.Created, response.status())
        }
    }

}
Okay. I think I found the problem. I was misinitializing modules with Koin. I was doing this:
Copy code
startKoin {
            module {
                single<OptionGroupController>()
                single<OptionGroupService>()
            }
        }
And now I do this and is working:
Copy code
private val optionGroupModules: Module = module {
    single { Conf }
    single { OptionGroupService() }
    single { OptionGroupController(get()) }
}
Copy code
startKoin { modules(optionGroupModules) }
n
currently i t seems like you ony call the routing block in the
withTestApplication
call if you write it like so
Copy code
withTestApplication(
    {
       install(Koin) { 
           modules(optionGroupModules)
       }
       routes() 
    }
) {
// test code here
}
it should work and this can be refactored into a utility function so you have the same setup of the test application each time
👏 1
m
Great! Thanks! 😄
In a new Util.kt file
Copy code
fun testFeaturesSetup(modules: Module): Application.() -> Unit {
    return {
        install(Koin) {
            modules(modules)
        }

        routes()
    }
}
In the test file
Copy code
private val optionModules: Module = module {
    single { Conf }
    single { OptionGroupService() }
    single { OptionService(get()) }
    single { OptionController(get()) }
    single { OptionGroupController(get()) }
}


@Test
    private fun `create option`() = withTestApplication(testFeaturesSetup(optionModules)) {
        with(handleRequest(<http://HttpMethod.Post|HttpMethod.Post>, "/optionGroup") {
            addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
            setBody(optionGroup)
        }) {
            assertEquals(HttpStatusCode.OK, response.status())

        }

        with(handleRequest(<http://HttpMethod.Post|HttpMethod.Post>, "/option") {
            addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
            setBody(option)
        }) {
            assertEquals(HttpStatusCode.OK, response.status())
        }
}
A lot better 🙂