I have a multiplatform library to do few APIs calls with Ktor (2.0.0-beta-1)
class DiscoveryServicesImpl(private val client: HttpClient) : DiscoveryServices {
override suspend fun getServers(domain: String): DAAServers {
return client.get(Servers.Domain(domain = domain)).body()
}
}
// Where client is created with specific engine (OkHttp for Android and Darwin for iOS)
This code works as expected (implemented in both Android and iOS apps)
To secure this code, I've added a unit test to verify that the url is well builded.
@Test
fun getServersSuccessful() {
runBlocking {
var _request: HttpRequestData? = null
//Given
val mockEngine = MockEngine {
_request = it
}
val discoveryApiMock = DiscoveryApi(mockEngine)
val service = DiscoveryServicesImpl(discoveryApiMock.client)
//When
val servers: DAAServers = service.getServers(domain)
//Then
assertEquals("https://****/$domain", _request!!.url.toString())
}
}
But when a run this test I got an error (for iOS test only) :
> Task :api:discovery:iosTest
***.discovery.DiscoveryServicesImplTest.getServersSuccessful FAILED
kotlin.native.concurrent.InvalidMutabilityException at /Users/teamcity1/teamcity_work/6326934d18cfe24e/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Throwable.kt:24
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.native.internal.Ref@15cb7c8
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.native.internal.Ref@15cb7c8
at kotlin.Throwable#<init>(/Users/teamcity1/teamcity_work/6326934d18cfe24e/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Throwable.kt:24)
at kotlin.Exception#<init>(/Users/teamcity1/teamcity_work/6326934d18cfe24e/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt:23)
at kotlin.RuntimeException#<init>(/Users/teamcity1/teamcity_work/6326934d18cfe24e/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt:34)
at kotlin.native.concurrent.InvalidMutabilityException#<init>(/Users/teamcity1/teamcity_work/6326934d18cfe24e/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:24)
at <global>.ThrowInvalidMutabilityException(/Users/teamcity1/teamcity_work/6326934d18cfe24e/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:109)
at <global>.MutationCheck(Unknown Source)
at kotlin.native.internal.Ref#<set-element>(/Users/teamcity1/teamcity_work/6326934d18cfe24e/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Ref.kt:12)
It's happening only on the ios target
To fix this, I've added this code pretty much everywhere (commonMain, commonTest, iosMain, iosTest) but it doesn't change anything
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt") {
version {
strictly("1.6.0-native-mt")
}
}
Below, my gradles files :
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(Ktor.clientCore)
implementation(Ktor.clientResources)
implementation(Ktor.contentNegotiation)
implementation(Ktor.clientJson)
implementation(Ktor.clientLogging)
implementation(Ktor.clientAuth)
implementation(Koin.koinMultiplatform)
implementation(project(":serialization"))
implementation(project(":transverse:log"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt") {
version {
strictly("1.6.0-native-mt")
}
}
}
}
val commonTest by getting {
dependencies {
implementation(Ktor.clientMock)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0-native-mt") {
version {
strictly("1.6.0-native-mt")
}
}
}
}
val iosMain by getting {
dependencies {
implementation(Ktor.clientDarwin)
}
}
}
}
If you're using the latest version of ktor and coroutines, you'll probably want to use the new memory model, and just the 1.6.0
kotlinx.coroutines rather than the native-mt version.
https://github.com/touchlab/KaMPKit/blob/main/gradle.properties#L26
Most library dev from Jetbrains will likely focus on the new memory model from now on, so unless there are specific near term concerns on moving, I would do that.