1

我正在尝试测试一个将自己声明为CoroutineScope. 该类有一些launch在其范围内工作的方法,我必须从测试方法中断言这些工作的效果。

这是我尝试过的:

import kotlinx.coroutines.*

class Main : CoroutineScope {
    override val coroutineContext get() = Job()

    var value = 0

    fun updateValue() {
        this.launch {
            delay(1000)
            value = 1
        }
    }
}

fun main() {
    val main = Main()
    val mainJob = main.coroutineContext[Job]!!
    main.updateValue()
    runBlocking {
        mainJob.children.forEach { it.join() }
    }
    require(main.value == 1)
}

我的期望是updateValue()coroutineContext. 但事实证明这mainJob.children是空的,所以我不能等待完成launch并且require语句失败。

使这项工作的正确方法是什么?

4

2 回答 2

1

我的代码中的错误很简单:

override val coroutineContext get() = Job()

我不小心留下了一个自定义 getter,这意味着每次访问都会coroutineContext创建一个新工作。自然,我在测试代码中得到的工作没有孩子。删除get()使代码工作:

override val coroutineContext = Job()
于 2018-11-16T09:50:38.803 回答
0

将您的协程构建器启动修改为

this.launch(start = CoroutineStart.LAZY) 

并将您的作业对象初始化更改为直接

override val coroutineContext : Job =   Job()  

它应该产生预期的结果

这是我试过的例子,它产生了预期的结果

import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext

class Main : CoroutineScope {

val scope: CoroutineScope = this

override val coroutineContext = Job()
    //Dispatchers.Default +

var value = 0

 fun updateValue(csc : CoroutineScope) {
    csc.launch(context = coroutineContext, start = CoroutineStart.LAZY) { println(this.coroutineContext[Job]!!.toString() + " job 2") }
    csc.launch (context = coroutineContext, start = CoroutineStart.LAZY){ println(this.coroutineContext[Job]!!.toString() + " job 3") }
    csc.launch (start = CoroutineStart.LAZY){
        println(this.coroutineContext[Job]!!.toString() + " job 1")
        //delay(1000)
        value = 1
    }

 }

fun something() {
    launch (start = CoroutineStart.LAZY){
        println(this.coroutineContext[Job]!!.toString() + " something 1")
    }

    launch (start = CoroutineStart.LAZY){
        println(this.coroutineContext[Job]!!.toString() + " something 2")
    }

    launch(start = CoroutineStart.LAZY) {
        println(this.coroutineContext[Job]!!.toString() + " something 3")
        delay(2000)
        value = 1
    }
}

}

fun main() {
    val main = Main()
    val mainJob = main.coroutineContext[Job]!!
    main.updateValue(main.scope)
    //main.something()
    runBlocking {
        //println(mainJob.children.count())
        println(mainJob.children.count())
        mainJob.children.forEach {
            //println("in run blocking")
            println(it.toString())
            it.join()
        }
    }
    println(main.value)
}


`
于 2018-11-16T01:54:05.397 回答