The Ktor 2.0 tests environment and its testApllicationn and externalServices is a great improvment ...
l

Laurent SOULET

over 3 years ago
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.
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.
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
Hi, I'm trying to upgrade Ktor Client to v3-beta-1 in my KMP application and I'm receiving the foll...
m

Mohammed Akram Hussain

almost 2 years ago
Hi, I'm trying to upgrade Ktor Client to v3-beta-1 in my KMP application and I'm receiving the following crash as soon as the application starts:
FATAL EXCEPTION: main
Process: app.storelab.storelabcore.android, PID: 3512
java.lang.NoClassDefFoundError: Failed resolution of: Lio/ktor/client/plugins/HttpTimeout;
	at io.ktor.client.engine.okhttp.OkHttpEngine.<init>(OkHttpEngine.kt:31)
	at io.ktor.client.engine.okhttp.OkHttp.create(OkHttp.kt:31)
	at app.storelab.storelabcore.android.MainActivity.onCreate(MainActivity.kt:24)
	at android.app.Activity.performCreate(Activity.java:8305)
	at android.app.Activity.performCreate(Activity.java:8284)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3626)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3782)
	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7872)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.ClassNotFoundException: Didn't find class "io.ktor.client.plugins.HttpTimeout" on path: DexPathList[[zip file "/data/app/~~UqQSjqTEOSPQYceuPM8PKA==/app.storelab.storelabcore.android-ntlIpREDE-tWKV-6fGwq_g==/base.apk"],nativeLibraryDirectories=[/data/app/~~UqQSjqTEOSPQYceuPM8PKA==/app.storelab.storelabcore.android-ntlIpREDE-tWKV-6fGwq_g==/lib/arm64, /system/lib64, /system_ext/lib64]]
	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
	at io.ktor.client.engine.okhttp.OkHttpEngine.<init>(OkHttpEngine.kt:31) 
	at io.ktor.client.engine.okhttp.OkHttp.create(OkHttp.kt:31) 
	at app.storelab.storelabcore.android.MainActivity.onCreate(MainActivity.kt:24) 
	at android.app.Activity.performCreate(Activity.java:8305) 
	at android.app.Activity.performCreate(Activity.java:8284) 
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417) 
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3626) 
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3782) 
	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101) 
	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307) 
	at android.os.Handler.dispatchMessage(Handler.java:106) 
	at android.os.Looper.loopOnce(Looper.java:201) 
	at android.os.Looper.loop(Looper.java:288) 
	at android.app.ActivityThread.main(ActivityThread.java:7872) 
	at java.lang.reflect.Method.invoke(Native Method) 
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
I'm not sure if there's any additional step required for this migration which I might be missing?
Hi, I am kotlin/exposed newbie and I am having trouble inserting into a table with a foreign key ref...
d

Deji

almost 4 years ago
Hi, I am kotlin/exposed newbie and I am having trouble inserting into a table with a foreign key reference. Please can someone tell me what I am doing wrong?
object Profile : IntIdTable("profile", "id") {
  val externalId: Column<String> = varchar("external_id",
    255).uniqueIndex("external_profile_external_id_uindex")

  val profileUrl: Column<String?> = varchar("profile_url",
    255).uniqueIndex("external_profile_profile_url_uindex").nullable()

  val imageUrl: Column<String?> = varchar("image_url", 255).nullable()

  val uri: Column<String> = varchar("uri", 255).uniqueIndex("external_profile_uri_uindex")
}

object User : IntIdTable("user", "id") {
  val username: Column<String> = varchar("username",
    20).uniqueIndex("internal_user_username_uindex")

  val email: Column<String> = varchar("email",
    255).uniqueIndex("internal_user_email_uindex")

  val displayName: Column<String?> = varchar("display_name", 255).nullable()

  val externalProfileId: Column<Int> =
    integer("profile_id").references(Profile.id).uniqueIndex("internal_user_external_profile_id_uindex")
}


val profile = Profile.insert {
  it[externalId] = "externalId"
  it[profileUrl] = "profileUrl"
  it[imageUrl] = "imageUrl"
  it[uri] = "uri"
}

val user = User.insert {
  it[username] = "username"
  it[email] = "email"
  it[displayName] = "displauName"
  it[externalProfileId] = profile[id] // <--- this line fails to compile
}
I cant set the externalProfileId foreign key to the ID from the new profile created. is there a better way to do this? Thanks!