Как использовать runBlocking, чтобы дождаться завершения CoroutineScope - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь протестировать класс, который объявляет себя как 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 не выполнен.

Как правильно сделать эту работу?

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Ошибка в моем коде была простой:

override val coroutineContext get() = Job()

Я случайно оставил пользовательский геттер, что означает, что каждый доступ к coroutineContext создавал новую работу. Естественно, работа, которую я получил в тестовом коде, не имела детей. Удаление get() заставляет код работать:

override val coroutineContext = Job()
0 голосов
/ 16 ноября 2018

измените свой запуск конструктора сопрограмм на

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


`
...