https://kotlinlang.org logo
#ktor
Title
# ktor
l

Laurent SOULET

06/07/2022, 3:58 PM
The Ktor 2.0 tests environment and its testApllicationn and externalServices is a great improvment ! Unfortunately I have a problem to test external services with timeouts. I don't know if I miss something or if it is a bug.
Copy code
package com.example

import io.ktor.client.*
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.testing.*
import kotlin.test.Test
import kotlin.test.assertEquals


fun Application.configureRouting(httpClient: HttpClient) {
    routing {
        get("/test") {
            httpClient.get("<http://fake.site.io/toto>") {
                timeout {
                    requestTimeoutMillis = 100
                }
            }
            call.respondText("Hello World!")
        }
    }
}


class ApplicationTest {
    @Test
    fun testRoot() = testApplication {

        val myClient = createClient {
            install(HttpTimeout)
        }

        application {
            configureRouting(myClient)
        }

        externalServices {
            hosts ("<http://fake.site.io>") {
                routing {
                    get("/toto") {
                        call.respond(HttpStatusCode.OK)
                    }
                }
            }
        }

        myClient.get("/test").apply {
            assertEquals(HttpStatusCode.OK, status)
        }
    }
}
When I execute this code, I receive this exception.
Copy code
Engine doesn't support io.ktor.client.plugins.HttpTimeout$Plugin@3db8b930
java.lang.IllegalArgumentException: Engine doesn't support io.ktor.client.plugins.HttpTimeout$Plugin@3db8b930
	at io.ktor.client.engine.HttpClientEngine$DefaultImpls.checkExtensions(HttpClientEngine.kt:101)
	at io.ktor.client.engine.HttpClientEngine$DefaultImpls.access$checkExtensions(HttpClientEngine.kt:23)
	at io.ktor.client.engine.HttpClientEngine$install$1.invokeSuspend(HttpClientEngine.kt:64)
	at io.ktor.client.engine.HttpClientEngine$install$1.invoke(HttpClientEngine.kt)
	at io.ktor.client.engine.HttpClientEngine$install$1.invoke(HttpClientEngine.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
	at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:101)
	at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
	at io.ktor.client.plugins.HttpSend$DefaultSender.execute(HttpSend.kt:135)
	at io.ktor.client.plugins.HttpRedirect$Plugin$install$1.invokeSuspend(HttpRedirect.kt:61)
	at io.ktor.client.plugins.HttpRedirect$Plugin$install$1.invoke(HttpRedirect.kt)
	at io.ktor.client.plugins.HttpRedirect$Plugin$install$1.invoke(HttpRedirect.kt)
	at io.ktor.client.plugins.HttpSend$InterceptedSender.execute(HttpSend.kt:113)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invokeSuspend(HttpCallValidator.kt:147)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invoke(HttpCallValidator.kt)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invoke(HttpCallValidator.kt)
	at io.ktor.client.plugins.HttpSend$InterceptedSender.execute(HttpSend.kt:113)
	at io.ktor.client.plugins.HttpSend$Plugin$install$1.invokeSuspend(HttpSend.kt:101)
	at io.ktor.client.plugins.HttpSend$Plugin$install$1.invoke(HttpSend.kt)
	at io.ktor.client.plugins.HttpSend$Plugin$install$1.invoke(HttpSend.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceedWith(SuspendFunctionGun.kt:91)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$1.invokeSuspend(HttpCallValidator.kt:126)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$1.invoke(HttpCallValidator.kt)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$1.invoke(HttpCallValidator.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
	at io.ktor.client.plugins.HttpRequestLifecycle$Plugin$install$1.invokeSuspend(HttpRequestLifecycle.kt:35)
	at io.ktor.client.plugins.HttpRequestLifecycle$Plugin$install$1.invoke(HttpRequestLifecycle.kt)
	at io.ktor.client.plugins.HttpRequestLifecycle$Plugin$install$1.invoke(HttpRequestLifecycle.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
	at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:101)
	at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
	at io.ktor.client.HttpClient.execute$ktor_client_core(HttpClient.kt:187)
	at io.ktor.client.statement.HttpStatement.executeUnsafe(HttpStatement.kt:107)
	at io.ktor.client.statement.HttpStatement.execute(HttpStatement.kt:46)
	at io.ktor.client.statement.HttpStatement.execute(HttpStatement.kt:61)
🧵 2
a

Aleksei Tirman [JB]

06/07/2022, 4:40 PM
Each engine has a list of capabilities that can include
HttpTimeout
,
WebSocketCapability
, and
WebSocketExtensionsCapability
. Unfortunately, the engine that is used for testing a server doesn’t support
HttpTimeout
capability.
l

Laurent SOULET

06/07/2022, 9:19 PM
Ok. The problem is that I don't need to test the timeout feature but just test that my route is called and because of this timeout set in the request builder I can't test the call of the route. Is there a possible workaround ?
a

Aleksei Tirman [JB]

06/08/2022, 9:57 AM
Unfortunately, I can’t find a workaround. I’ve created an issue to address this problem.
l

Laurent SOULET

06/08/2022, 10:27 AM
Thanks a lot 👍
232 Views