so trying to understand how I can make testing ktor app with testcontainers
this is my code
package com.app
import com.app.base.db.DbFactory
import com.app.features.auth.RegisterDTO
import com.app.plugins.*
import io.kotest.assertions.ktor.client.shouldHaveStatus
import io.kotest.core.extensions.install
import io.kotest.core.spec.style.FreeSpec
import io.kotest.extensions.testcontainers.JdbcTestContainerExtension
import io.ktor.client.*
import io.ktor.client.engine.apache.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import org.testcontainers.containers.PostgreSQLContainer
import io.ktor.server.testing.*
import kotlinx.serialization.json.Json
import org.jetbrains.exposed.sql.Database
class AuthSpec : FreeSpec({
val postgres = PostgreSQLContainer<Nothing>("postgres").apply {
withDatabaseName("test_appDB")
startupAttempts = 1
withUsername("test_viktor")
withPassword("test_longPass")
withExposedPorts(5432)
}
postgres.start()
val ds = install(JdbcTestContainerExtension(postgres)) {
poolName = "myconnectionpool"
maximumPoolSize = 8
idleTimeout = 10000
}
"register creator" - {
testApplication {
application {
DbFactory.init(ds)
configureSecurity()
configureHTTP()
configureMonitoring()
configureSerialization()
configureDependencyInjection()
configureStatusPage()
configureRouting()
}
val client = HttpClient(Apache) {}
client.post("/api/v1/auth/register") {
contentType(ContentType.Application.Json)
setBody(RegisterDTO("[email protected]", "some", "some@sdfSDF"))
}.apply {
this.shouldHaveStatus(HttpStatusCode.OK)
}
}
}
})
I do expect that this test will run correctly and I can see the green in tests but actually i see the error
Fail to serialize body. Content has type: class com.app.features.auth.RegisterDTO, but OutgoingContent expected.
java.lang.IllegalStateException: Fail to serialize body. Content has type: class com.app.features.auth.RegisterDTO, but OutgoingContent expected.
If you expect serialized body, please check that you have installed the corresponding plugin(like `ContentNegotiation`) and set `Content-Type` header.
at io.ktor.client.plugins.HttpSend$Plugin$install$1.invokeSuspend(HttpSend.kt:87)
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)
at com.app.AuthSpec$1$1$1.invokeSuspend(AuthSpec.kt:84)
i have installed a lot of libraries for tests probably they are not needed but here are they in dependendancies
//region tests
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
testImplementation("io.ktor:ktor-server-test-host:$ktor_version")
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version")
testImplementation("io.kotest:kotest-runner-junit5:$kotest_version")
testImplementation("io.kotest:kotest-assertions-core:$kotest_version")
testImplementation("io.kotest:kotest-property:$kotest_version")
testImplementation("io.kotest.extensions:kotest-extensions-testcontainers:1.3.2")
testImplementation("org.testcontainers:testcontainers:$testcontainers_version")
testImplementation("org.testcontainers:junit-jupiter:$testcontainers_version")
testImplementation("org.testcontainers:postgresql:$testcontainers_version")
testImplementation("io.kotest.extensions:kotest-assertions-ktor:1.0.3")
//endregion
CodePudding user response:
You need to install the ContentNegotiation plugin by configuring the test client.