Interview frequency: …
Short answer
Using runTest, which automatically skips over time delays (delay skipping), and replacing Dispatchers.Main with a test dispatcher through Dispatchers.setMain.
Explanation
Without runTest, calling a function containing delay(10_000L) would make the test wait 10 real seconds. The runTest environment controls virtual time and automatically jumps the virtual clock. StandardTestDispatcher provides manual scheduling of tasks through advanceUntilIdle() or advanceTimeBy(), while UnconfinedTestDispatcher executes new tasks eagerly and immediately without waiting.
Code example
@OptIn(ExperimentalCoroutinesApi::class)
class CoroutineTest {
private val testDispatcher = StandardTestDispatcher()
@Before
fun setUp() { Dispatchers.setMain(testDispatcher) }
@After
fun tearDown() { Dispatchers.resetMain() }
@Test
fun delayedOperation_completesImmediately() = runTest(testDispatcher) {
val deferred = async { delay(5000L); "Done" }
advanceUntilIdle() // Jumps through five virtual seconds in a fraction of a millisecond!
assertEquals("Done", deferred.getCompleted())
}
}Common mistakes
- Forgetting to call Dispatchers.setMain at the start of tests that use viewModelScope, causing an IllegalStateException crash because the main thread's looper is missing.