Bird
Raised Fist0
Kotlinprogramming~20 mins

Testing coroutines with runTest in Kotlin - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Coroutine Testing Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output of this coroutine test using runTest?
Consider this Kotlin coroutine test using runTest. What will be printed when the test runs?
Kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.test.runTest

fun fetchData(): String = "Data"

@OptIn(ExperimentalCoroutinesApi::class)
suspend fun fetchDataAsync(): String = coroutineScope {
    delay(100)
    fetchData()
}

@OptIn(ExperimentalCoroutinesApi::class)
suspend fun main() = runTest {
    val result = fetchDataAsync()
    println(result)
}
AData
Bnull
CException in thread "main" java.lang.IllegalStateException
DNo output (test hangs)
Attempts:
2 left
💡 Hint
runTest executes coroutines in a controlled environment and waits for completion.
🧠 Conceptual
intermediate
1:30remaining
Which statement about runTest is true?
Choose the correct statement about the runTest function in Kotlin coroutine testing.
ArunTest disables all coroutine dispatchers during the test.
BrunTest launches coroutines but does not wait for their completion.
CrunTest automatically advances virtual time to handle delays inside coroutines.
DrunTest can only be used with blocking code, not suspend functions.
Attempts:
2 left
💡 Hint
Think about how runTest handles delays without slowing down tests.
🔧 Debug
advanced
2:00remaining
What error does this coroutine test raise?
This test uses runTest but throws an error. What is the error type?
Kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.test.runTest

@OptIn(ExperimentalCoroutinesApi::class)
suspend fun faultyFunction() {
    withContext(Dispatchers.IO) {
        delay(50)
    }
}

@OptIn(ExperimentalCoroutinesApi::class)
suspend fun main() = runTest {
    faultyFunction()
}
AIllegalStateException: Dispatchers.IO is not allowed inside runTest
BTimeoutCancellationException
CNo error, runs successfully
DUnresolved reference: Dispatchers
Attempts:
2 left
💡 Hint
runTest restricts usage of certain dispatchers to keep tests deterministic.
📝 Syntax
advanced
1:30remaining
Which option correctly uses runTest to test a suspend function?
Select the code snippet that correctly tests a suspend function using runTest.
A
runTest {
    launch {
        val result = suspendFunction()
        assert(result == 42)
    }
}
B
runTest {
    val result = suspendFunction()
    println(result)
}
Thread.sleep(100)
C
runTest {
    suspendFunction()
}
println("Test done")
D
runTest {
    val result = suspendFunction()
    assert(result == 42)
}
Attempts:
2 left
💡 Hint
runTest waits for all coroutines inside its block to complete before returning.
🚀 Application
expert
2:30remaining
How many items are in the list after this runTest block?
Given this Kotlin coroutine test using runTest, how many items does the list contain after execution?
Kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.test.runTest

@OptIn(ExperimentalCoroutinesApi::class)
suspend fun addItems(list: MutableList<Int>) {
    coroutineScope {
        launch {
            delay(50)
            list.add(1)
        }
        launch {
            delay(100)
            list.add(2)
        }
    }
}

@OptIn(ExperimentalCoroutinesApi::class)
suspend fun main() = runTest {
    val items = mutableListOf<Int>()
    addItems(items)
    println(items.size)
}
ATest hangs and prints nothing
B2
C1
D0
Attempts:
2 left
💡 Hint
runTest waits for all child coroutines launched inside coroutineScope to finish.

Practice

(1/5)
1. What is the main purpose of using runTest in Kotlin coroutine testing?
easy
A. To run coroutine tests quickly and safely
B. To create new threads for coroutines
C. To convert coroutines into blocking calls
D. To disable coroutine dispatchers

Solution

  1. Step 1: Understand the role of runTest

    runTest is designed to run coroutine tests in a controlled environment that is fast and safe.
  2. Step 2: Compare options with runTest purpose

    Options A, B, and D describe unrelated or incorrect behaviors. Only To run coroutine tests quickly and safely correctly states the purpose.
  3. Final Answer:

    To run coroutine tests quickly and safely -> Option A
  4. Quick Check:

    runTest purpose = run coroutine tests quickly and safely [OK]
Hint: Remember: runTest runs coroutine tests safely and fast [OK]
Common Mistakes:
  • Thinking runTest creates new threads
  • Confusing runTest with blocking calls
  • Assuming runTest disables dispatchers
2. Which of the following is the correct syntax to start a coroutine test using runTest?
easy
A. runTest[] { val result = suspendFunction() }
B. runTest() => { val result = suspendFunction() }
C. runTest { val result = suspendFunction() }
D. runTest -> { val result = suspendFunction() }

Solution

  1. Step 1: Recall the correct runTest syntax

    The correct syntax uses parentheses with a lambda block: runTest { ... }.
  2. Step 2: Check each option's syntax

    runTest { val result = suspendFunction() } matches the correct syntax. Options B, C, and D use invalid Kotlin syntax for lambdas.
  3. Final Answer:

    runTest { val result = suspendFunction() } -> Option C
  4. Quick Check:

    Correct runTest syntax = runTest { ... } [OK]
Hint: Use curly braces {} after runTest for coroutine tests [OK]
Common Mistakes:
  • Using parentheses with arrow syntax incorrectly
  • Using square brackets instead of braces
  • Using arrow (->) instead of braces for lambda
3. What will be the output of this Kotlin test code using runTest?
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.delay

fun suspendFunction(): String {
    delay(100)
    return "Done"
}

fun main() {
    println(suspendFunction())
}
medium
A. Done
B. Compilation error
C. Runtime exception
D. No output

Solution

  1. Step 1: Analyze the suspend function usage

    suspendFunction contains delay(100) call, which requires a suspend function context, but suspendFunction itself is not marked as suspend.
  2. Step 2: Check for compilation errors

    Calling suspend functions like delay inside a non-suspend function causes a compilation error.
  3. Final Answer:

    Compilation error -> Option B
  4. Quick Check:

    Calling delay requires suspend context = compilation error if missing [OK]
Hint: delay must be called from suspend context [OK]
Common Mistakes:
  • Assuming suspend functions like delay can be called from normal functions
  • Expecting output without suspend keyword
  • Ignoring suspend function rules
4. Identify the error in this coroutine test code using runTest and how to fix it:
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.delay

fun suspendFunction(): String {
    delay(100)
    return "Done"
}

fun main() = runTest {
    val result = suspendFunction()
    println(result)
}
medium
A. suspendFunction should be marked suspend
B. runTest cannot be called inside main
C. delay cannot be used inside runTest
D. println cannot be used inside runTest

Solution

  1. Step 1: Check suspendFunction declaration

    suspendFunction calls delay(100) but is not marked as suspend, which is incorrect for coroutine code.
  2. Step 2: Fix by marking suspendFunction as suspend

    Marking suspendFunction as suspend allows it to be called inside runTest properly.
  3. Final Answer:

    suspendFunction should be marked suspend -> Option A
  4. Quick Check:

    suspendFunction missing suspend keyword = error [OK]
Hint: Mark functions calling coroutines as suspend [OK]
Common Mistakes:
  • Not marking suspendFunction as suspend
  • Thinking runTest can't be in main
  • Believing delay is disallowed in runTest
5. You want to test a suspend function fetchData() that returns a string after a delay. Which is the best way to write a test using runTest to verify it returns "Success"?
hard
A. runTest { val result = fetchData(); assert(result == "Success") }
B. runTest { val result = fetchData(); println(result) }
C. runBlocking { val result = fetchData(); assert(result == "Success") }
D. runTest { val result = fetchData(); assertEquals("Success", result) }

Solution

  1. Step 1: Choose correct test function and assertion

    runTest is the recommended coroutine test runner. Using assertEquals is the standard way to check expected results in tests.
  2. Step 2: Compare options for best practice

    runTest { val result = fetchData(); assertEquals("Success", result) } uses runTest and assertEquals, making it the best choice. runTest { val result = fetchData(); assert(result == "Success") } uses assert but not the standard function. runTest { val result = fetchData(); println(result) } only prints result. runBlocking { val result = fetchData(); assert(result == "Success") } uses runBlocking which is less preferred for coroutine tests.
  3. Final Answer:

    runTest { val result = fetchData(); assertEquals("Success", result) } -> Option D
  4. Quick Check:

    Use runTest + assertEquals for coroutine tests [OK]
Hint: Use runTest with assertEquals to verify coroutine results [OK]
Common Mistakes:
  • Using runBlocking instead of runTest
  • Using print instead of assertions
  • Using assert instead of assertEquals
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard