https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
m

mike.holler

10/07/2020, 8:13 PM
Anyone have any pointers for testing suspend functions in commonTest? I've tried depending on
kotlinx-coroutines-test
to help me with this, but unfortunately I ended up getting an error.
Copy code
val commonMain by getting {
    dependencies {
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9")
        implementation("io.ktor:ktor-client-core:1.4.0")
    }
}
val commonTest by getting {
    dependencies {
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9")
        implementation(kotlin("test-common"))
        implementation(kotlin("test-annotations-common"))
    }
}
Error:
Copy code
Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could not resolve org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9.
Required by:
    project :
Caused by: org.gradle.internal.component.NoMatchingConfigurationSelectionException: No matching variant of org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9 was found. The consumer was configured to find a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js', attribute 'org.jetbrains.kotlin.js.compiler' with value 'legacy' but:
  - Variant 'apiElements' capability org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9:
      - Incompatible because this component declares an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' and the consumer needed a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
      - Other compatible attribute:
          - Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
  - Variant 'runtimeElements' capability org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9 declares a runtime of a component:
      - Incompatible because this component declares a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' and the consumer needed a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
      - Other compatible attribute:
          - Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
When I remove the
kotlinx-coroutines-test
line, I no longer get this error but of course then cannot test coroutines.
t

Tijl

10/07/2020, 8:15 PM
it is jvm only so you can only declare it as a dependency for your
android*Test
or
jvmTest
sourcesets
m

mike.holler

10/07/2020, 8:16 PM
That's sad, but thanks for the response @Tijl. Any ideas about what approach to use in testing suspend functions in
commonTest
then?
I found something that looks like it might work that uses
kotest
but I'd rather avoid bringing another test framework into this.
t

Tijl

10/07/2020, 8:24 PM
in my experience using coroutines-test can also lead to bad results, after all you are testing the test dispatcher, and not the real one your program will use. obviously it can be nice to have, but it’s not impossible to write tests without it.
m

mike.holler

10/07/2020, 8:28 PM
but it’s not impossible to write tests without it.
@Tijl this is what I'm interested in. I don't know how to get started with writing tests that are capable of being run in commonTest with coroutines. I'm having trouble finding resources.
t

Tijl

10/07/2020, 8:32 PM
just use
runBlocking
to run your entire test (and any other scopes from there). if you need different behaviour for testing use the familiar injection patterns.
I often use Deferreds and await (from the test thread) to check in a linear way that the behaviour is correct from collectors etc
m

mike.holler

10/07/2020, 8:34 PM
runBlocking
is not available in
common
or
js
, it's purely a JVM and native feature.
t

Tijl

10/07/2020, 8:41 PM
you can easily expect/actual it for all platforms except js, and on JS use a promise based implementation
m

mike.holler

10/07/2020, 8:50 PM
I'm out of my depth here, and begging for examples. I appreciate your help, but I don't really know what to do with writing Kotlin commonTest code, which is the goal here. I want the same code to test my JVM and JS implementation. If I do a promise-based implementation of test code, it would only work in JS because promises don't work on the JVM. Basically, the opposite problem. I want one test suite that targets multiple languages.
I've found this approach, suggested here: https://github.com/Kotlin/kotlinx.coroutines/issues/885
t

Tijl

10/08/2020, 11:37 AM
yes, that’s the exact I approach I recommended using expect/actual, but with good example code. I hope it makes sense now.
2 Views