InvalidMutabilityExceptionInvalidMutabilityException 与 Ktor 共同测试

InvalidMutabilityExceptionInvalidMutabilityException on common test with Ktor

我有一个多平台库,可以使用 Ktor (2.0.0-beta-1) 进行少量 API 调用

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)

此代码按预期工作(在 Android 和 iOS 应用程序中实现)

为了确保此代码的安全,我添加了一个单元测试来验证 url 是否构建良好。

@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())
    }

}

但是当 运行 这个测试时我得到了一个错误(仅针对 iOS 测试):

> 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)

它只发生在 ios 目标上

为了解决这个问题,我几乎在所有地方都添加了这段代码(commonMain、commonTest、iosMain、iosTest),但它没有改变任何东西

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt") {
    version {
        strictly("1.6.0-native-mt")
    }
}

下面是我的 gradles 文件:

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)
            }
        }
    }
}

如果您使用的是最新版本的 ktor 和协程,您可能希望使用新的内存模型,并且只是 1.6.0 kotlinx.coroutines 而不是 native-mt版本。

https://blog.jetbrains.com/kotlin/2021/08/try-the-new-kotlin-native-memory-manager-development-preview/

https://github.com/touchlab/KaMPKit/blob/main/gradle.properties#L26

从现在开始,Jetbrains 的大多数库开发人员可能会专注于新的内存模型,因此除非近期有关于移动的具体问题,否则我会这样做。