Richard Hajdu
07/19/2023, 7:04 PMAleksei Tirman [JB]
07/20/2023, 7:01 AMRichard Hajdu
07/20/2023, 7:26 AMMockEngine in tests, but the example for configuring engines in multiplatform projects says that the engine should be defined only by the platform and not by the client implementation, but this way I cannot exchange the engine in tests.Richard Hajdu
07/20/2023, 7:32 AMMockEngine in tests?Aleksei Tirman [JB]
07/20/2023, 2:18 PMRichard Hajdu
07/20/2023, 2:23 PMAleksei Tirman [JB]
07/20/2023, 2:24 PMRichard Hajdu
07/20/2023, 2:25 PMRichard Hajdu
07/24/2023, 6:25 AMNo transformation found: class io.ktor.utils.io.ByteBufferChannel (Kotlin reflection is not available) -> class dev.drathar.poktor.model.move.MoveTarget (Kotlin reflection is not available)
with response from http://localhost/api/v2/move-target/specific-move:
status: 200 OK
response headers:
Content-Type: application/jsonI don't have the slightest clue on why the requests are targeting
localhost.
The client configuration I'm using is
internal class DefaultApiClient(mockEngine: HttpClientEngine? = null) : ApiClient {
override val httpClient = httpClient(mockEngine!!) {
defaultRequest {
url {
protocol = URLProtocol.HTTPS
host = "<http://pokeapi.co|pokeapi.co>"
path("api/v2/")
}
}
install(HttpCache)
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
})
}
}
}
where the httpClient function is declared as
expect fun httpClient(mockEngine: HttpClientEngine? = null, config: HttpClientConfig<*>.() -> Unit = {}): HttpClient
and defined on JVM as
actual fun httpClient(mockEngine: HttpClientEngine?, config: HttpClientConfig<*>.() -> Unit) = mockEngine?.let(::HttpClient) ?: HttpClient(OkHttp) {
config(this)
engine {
config {
retryOnConnectionFailure(true)
connectTimeout(0, TimeUnit.SECONDS)
}
}
}
All my tests are currently in the commonTest module.
Do you have any idea on what the problem might be @Aleksei Tirman [JB]?Aleksei Tirman [JB]
07/30/2023, 8:38 AMRichard Hajdu
07/30/2023, 8:58 AMinternal class BerriesApiClient(mockEngine: HttpClientEngine? = null) : BerriesApi, ApiClient by DefaultApiClient(mockEngine) { ... }
and in a corresponding test I'd create the client as
private fun createClient(response: String): BerriesApiClient {
val mockEngine = MockEngine {
respond(
content = response, headers = headersOf(HttpHeaders.ContentType, "application/json")
)
}
return BerriesApiClient(mockEngine)
}Richard Hajdu
08/02/2023, 6:30 AMAleksei Tirman [JB]
08/02/2023, 6:35 AMMoveTarget but the body hasn't been transformed to that type (usually by the ContentNegotiation plugin).Richard Hajdu
08/03/2023, 10:57 AMlocalhost, isn't that sus? I mean, if the MockEngine would be used it shouldn't be the case, right?Aleksei Tirman [JB]
08/03/2023, 11:31 AMMockEngine because if you don't explicitly specify the host then the localhost is assumed.Richard Hajdu
08/03/2023, 3:55 PMinternal class DefaultApiClient(engine: HttpClientEngine) : ApiClient {
override val httpClient = HttpClient(engine) {
defaultRequest {
url {
protocol = URLProtocol.HTTPS
host = "<http://pokeapi.co|pokeapi.co>"
path("api/v2/")
}
}
install(HttpCache)
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
})
}
}
}
and don't modify the unit tests, everything works fine, but as soon as I replace the HttpClient with the platform-specific one (which AFAIK inherits the ContentNegotiation plugin from the shared config defined above) it just falls apart.
I'll have time to dig deeper into this tomorrow, I'll try to identify the root cause.Richard Hajdu
08/04/2023, 9:40 AMContentNegotiation plugin, because I didn't config the HttpClient properly with the optional MockEngine.
The code before
actual fun httpClient(mockEngine: HttpClientEngine?, config: HttpClientConfig<*>.() -> Unit) = mockEngine?.let(::HttpClient) ?: HttpClient(OkHttp) {
config(this)
...
}
and after
actual fun httpClient(mockEngine: HttpClientEngine?, config: HttpClientConfig<*>.() -> Unit) = mockEngine?.let { HttpClient(it) { config(this) } } ?: HttpClient(OkHttp) {
config(this)
...
}
See how I simply created the HttpClient using the default constructor without configuring the engine properly before.