2017-11-08 75 views
13

Próbuję przeprowadzić test jednostkowy corntine Kotlina, który używa delay(). Dla testu jednostkowego nie interesuje mnie delay(), to tylko spowalnia test. Chciałbym uruchomić test w pewien sposób, który nie opóźnia się automatycznie, gdy wywoływany jest delay().Jednostka testująca coroutine Kotlin z opóźnieniem

Próbowałem uruchomiony współprogram użyciu kontekstu niestandardową, która deleguje do CommonPool:

class TestUiContext : CoroutineDispatcher(), Delay { 
    suspend override fun delay(time: Long, unit: TimeUnit) { 
     // I'd like it to call this 
    } 

    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) { 
     // but instead it calls this 
    } 

    override fun dispatch(context: CoroutineContext, block: Runnable) { 
     CommonPool.dispatch(context, block) 
    } 
} 

Miałem nadzieję, że właśnie wraca z delay() sposobu mojego kontekstu, ale zamiast tego dzwoni moja metoda scheduleResumeAfterDelay() i I don” t wiedzieć, jak przekazać to do domyślnego harmonogramu.

+0

Nie możesz po prostu ustawić limitu czasu opóźnienia, aby w teście można było wybrać bardzo mały ?! – s1m0nw1

+0

@ s1m0nw1 Tak, ale wolałbym ogólne rozwiązanie i nie musiałbym modyfikować mojego kodu w ten sposób. –

+0

@eoinmullan, Czy możesz podzielić się minimalnym projektem git dla tego samego? –

Odpowiedz

7

Jeśli nie chcemy żadnego opóźnienia, dlaczego nie można po prostu wznowić kontynuacji w zaproszeniu harmonogram ?:

class TestUiContext : CoroutineDispatcher(), Delay { 
    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) { 
     continuation.resume(Unit) 
    } 

    override fun dispatch(context: CoroutineContext, block: Runnable) { 
     //CommonPool.dispatch(context, block) // dispatch on CommonPool 
     block.run() // dispatch on calling thread 
    } 
} 

tamtędy delay() zostanie wznowiony bez opóźnień. Należy pamiętać, że to wciąż wstrzymuje się zwłoki, tak aby inni współprogram może nadal działać (jak yield())

@Test 
fun `test with delay`() { 
    runBlocking(TestUiContext()) { 
     launch { println("launched") } 
     println("start") 
     delay(5000) 
     println("stop") 
    } 
} 

działa bez zwłoki i druki:

start 
launched 
stop 

EDIT:

Można kontrolować, gdzie kontynuacja jest wykonywana przez dostosowanie funkcji dispatch.

+0

A 'dispatch()' może po prostu być 'block.run()', który utrzymuje wykonanie w głównym wątku. –

+0

To prawda, i to może mieć sens w testowaniu, chociaż wydawało się, że chce używać CommonPool. – bj0

+0

Jestem OP, i wolałbym, żeby używał tego samego wątku. Dokonaj zmiany, a ja przyjmuję twoją odpowiedź. –