Day 25: 准备假的Coroutine,让外面世界不会影响我!

Keyword: Coroutine mock
直到27日,完成KMM的测试功能放在
KMMDay27


今天开始要来写KMM的测试,由於我们使用DB或是进行网路请求都是suspend function,所以需要先撰写一个给测试使用的基础Coroutine方便我们进行测试.

首先,在CommonTest的专案底下,建立一个expect物件,BaseTest,里面只有一个runTest的方法.

//这是在commonTest底下的Kotlin
import kotlinx.coroutines.CoroutineScope

expect abstract class BaseTest() {
    fun <T> runTest(block: suspend CoroutineScope.() -> T)
}

有了expect当然就需要去双平台实作actual让双平台在测试时候有办法使用,跟commonMain的expect物件一样.必须有同样的packagePath

Android的实作方法如下,其中的coroutineTestRule是我们自己写的Rule,他会在测试开始与结束时重设Dispather,避免测试的顺序影响到测试的结果..

// 这是在androidTest 底下的Kotlin
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
actual abstract class BaseTest {
    @get:Rule
    var coroutineTestRule = CoroutineTestRule()

    actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
        runBlocking { block() }
    }
}

CouroutineTestRule如下,非常简单的结构

// 这是在androidTest 底下的Kotlin
class CoroutineTestRule(
    private val testDispatcher: ExecutorCoroutineDispatcher = Executors.newSingleThreadExecutor()
        .asCoroutineDispatcher()
) : TestWatcher() {
    override fun starting(description: Description?) {
        super.starting(description)
        Dispatchers.setMain(testDispatcher)//设定Main
    }

    override fun finished(description: Description?) {
        super.finished(description)
        Dispatchers.resetMain()//重设Main
    }
}

这边我们有用到junit等等的常用测试工具,所以要在gradle(shared)的androidTest部分加上他们的引用

//这是在build.gradle.kts中的Kotlin

...
val androidTest by getting {
            dependencies {
                ...
                implementation(Develop.KotlinTest.jvm)
                implementation(Develop.KotlinTest.junit)
                implementation(Develop.AndroidXTest.core)
                implementation(Develop.AndroidXTest.junit)
                implementation(Develop.AndroidXTest.runner)
                implementation(Develop.AndroidXTest.rules)
						...
            }
        }
...
//这是在buildSrc内的Kotlin设定

Develop{
object AndroidXTest {
        val core = "androidx.test:core:${Versions.AndroidX.test}"
        val junit = "androidx.test.ext:junit:${Versions.AndroidX.test_ext}"
        val runner = "androidx.test:runner:${Versions.AndroidX.test}"
        val rules = "androidx.test:rules:${Versions.AndroidX.test}"
    }
object KotlinTest {
        val common = "org.jetbrains.kotlin:kotlin-test-common:${Versions.kotlin}"
        val annotations = "org.jetbrains.kotlin:kotlin-test-annotations-common:${Versions.kotlin}"
        val jvm = "org.jetbrains.kotlin:kotlin-test:${Versions.kotlin}"
        val junit = "org.jetbrains.kotlin:kotlin-test-junit:${Versions.kotlin}"
    }
}
Versions{
val kotlin = "1.5.21"
}

这样我们就准备好Android的测试Coroutine了,接下来再去实作iOS使用的测试Coroutine

同样的,在同样的package path下,建立与expect同名的actual实作

//这是在iosTest底下的Kotlin语言
actual abstract class BaseTest {
    @OptIn(DelicateCoroutinesApi::class)
    actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
        var error: Throwable? = null
//由於iOS没有Coroutine环境,所以改成GlobalScope来进行测试
        GlobalScope.launch(Dispatchers.Main) {
            try {
                block()
            } catch (t: Throwable) {
                error = t
            } finally {
                CFRunLoopStop(CFRunLoopGetCurrent())//这边是由Native提供的iOS方法
            }
        }
        CFRunLoopRun()//这边是由Native提供的iOS方法
        error?.also { throw it }
    }
}

有了这两个基础的测试後,就有coroutine环境可以进行更进一步的测试


<<:  成为工具人应有的工具包-15 PasswordFox

>>:  D15 - 彭彭的课程# Python 函式参数详解:参数预设值、名称对应、任意长度参数(2)

Day21. Blue Prism 有事不再找老大,自己搞定 -BP 的Exception Type 与Exception Handling

常听说出事了就想找老大摆平, 结果在群内的地位越来越低, 如果能试着自己处理问题, 把事情Handl...

30天学会 Python: Day 0- 关於直译

接续此篇: https://ithelp.ithome.com.tw/articles/102649...

[Day25] Tableau 轻松学 - TabPy 使用方法 2

前言 直接将所有 Python 程序写在工作簿内的第一种 TabPy 使用方法我们已经学会了,但这种...

数据分析的好夥伴 - Python基础:档案读写

档案的读写算是Python非常实用的一环,可以帮助我们去编辑、储存或是新增建立一个档案。 在Pyrh...

Day3 — 前导:电晶体如何组成逻辑闸

如果用非常概括性的说法来描述 CPU 的组成,其实就是数以亿计的电晶体组合而成的。那麽电晶体又是怎麽...