Multiplatform project - testing coroutines in common module

I have difficulties integrating kotlin testing framework for coroutines kotlinx.coroutines.test with multiplatform project that targets Android (and ios in the future)

My common code relies heavily on coroutines but I’m unable to test them (it looks like the testing library is not in the classpath?)

build.gradle for common module:

plugins {
    id 'org.jetbrains.kotlin.multiplatform'
    id 'com.android.library'
    id 'kotlin-kapt'
}

android {
    defaultConfig {
        compileSdkVersion 28
        javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true
    }
    lintOptions {
        checkAllWarnings true
    }
}

def coroutinesVersion = "1.3.0-M2"
def mockKVersion = "1.9.3"

kotlin {
    targets {
        fromPreset(presets.android, 'android')
    }

    sourceSets {
        commonMain.dependencies {
            //Kotlin
            implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
            implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" //used in Log implementation
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutinesVersion"
        }
        commonTest.dependencies {
            //Kotlin
            implementation "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
            implementation "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
            //Coroutines testing
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutinesVersion"
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion"
            implementation "io.mockk:mockk-common:$mockKVersion"
        }
        androidMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
        }
        androidTest.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
            implementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
            implementation "io.mockk:mockk:$mockKVersion"
        }
    }
}

/*
* Due to the current limitations, it requires that the Android target is created before the kapt dependencies are configured,
* which needs to be done in a top-level dependencies { ... } block rather than within Kotlin source sets dependencies.
*/
dependencies {
    implementation 'javax.annotation:javax.annotation-api:1.3.2'
    kapt 'com.google.auto.factory:auto-factory:1.0-beta6@jar'
    compileOnly "com.google.auto.factory:auto-factory:1.0-beta6"
}

Example test in commonTest source set:

package some.package.common.test

import kotlin.test.Test
import kotlin.test.assertTrue

class SomeTest {

    @Test
    fun `should pass`() {
        //none of the kotlinx.coroutines.test content is available here (eg. runBlockingTest)
        assertTrue { 2 + 2 == 4 }
    }
}

What is the preffered way to test methods (suspended functions, ordinary functions starting new coroutines via launch, etc.) that are implemented in commonMain sourceSet?

kotlinx.coroutines.test is a JVM library, you can’t use it in common code. The best way to test multiplatform coroutines is to build your own multiplatofme runTest function that will use runBlocking on JVM/Native and Promise on JS

2 Likes

You can run JVM tests in an Android module. But common code cannot be directly tested, it can only be tested on a platform. The tests can be common code and shared for all platforms. In that case you can run them on all supported platforms.

1 Like

Thank you for the explanation.