---
title: "Your Coroutine Tests Are Flaky Because You Have Two Clocks Running"
url: https://daily.dev/posts/your-coroutine-tests-are-flaky-because-you-have-two-clocks-running-nwzhmolh7
source_url: https://proandroiddev.com/your-coroutine-tests-are-flaky-because-you-have-two-clocks-running-dfc2382909af
type: article
source: "ProAndroidDev"
published: 2026-08-16T17:44:13.877Z
updated: 2026-08-16T17:44:40.851Z
tags: ["testing", "android", "kotlin"]
reading_time: 8
upvotes: 2
comments: 0
language: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Your Coroutine Tests Are Flaky Because You Have Two Clocks Running

**[ProAndroidDev](https://daily.dev/sources/pand)** · 8 min read · 2 upvotes · 0 comments

## Summary

Flaky coroutine tests often stem from two clocks running simultaneously: the virtual clock provided by TestScope/TestCoroutineScheduler and a real clock when code switches to a real dispatcher like Dispatchers.IO. The fix is dependency-injecting dispatchers so tests can substitute a TestDispatcher, plus using Dispatchers.setMain() to replace the Main dispatcher for ViewModel coroutines. The piece contrasts StandardTestDispatcher (queued, controlled execution) with UnconfinedTestDispatcher (eager execution), and warns against overusing advanceUntilIdle(), which only controls the fake clock and can hang forever on infinite producers. Recommends runCurrent(), advanceTimeBy(), and backgroundScope.launch() as more precise alternatives.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://proandroiddev.com/your-coroutine-tests-are-flaky-because-you-have-two-clocks-running-dfc2382909af>

## Questions this post answers

### Why does my Kotlin coroutine test pass locally but fail flakily on CI?

It usually happens because part of the coroutine runs on the virtual clock inside runTest, while another part switches to a real dispatcher like Dispatchers.IO and runs on a real thread pool with non-deterministic timing. The test assertion can race that real work, passing on a fast machine but failing on a busier CI runner. Injecting dispatchers so tests can substitute a TestDispatcher fixes the race.

_daily.dev surfaces practical fixes like this for developers chasing down flaky coroutine test failures._

### What is the difference between StandardTestDispatcher and UnconfinedTestDispatcher in kotlinx-coroutines-test?

StandardTestDispatcher queues coroutine work and runs nothing until the scheduler is explicitly advanced (via runCurrent, advanceTimeBy, or advanceUntilIdle), making it useful for testing debounces, timeouts, or in-between states. UnconfinedTestDispatcher starts coroutines immediately and runs until the first suspension point, which is simpler when execution order control isn't needed.

_Developers comparing coroutine test dispatchers can track patterns like this on daily.dev._

### Why does advanceUntilIdle() sometimes make my coroutine test hang forever?

advanceUntilIdle() runs everything queued on the test scheduler until no suspension points remain, but it only sees the virtual clock and has no control over work that escaped to a real dispatcher. If a coroutine runs an infinite producer, such as a polling flow with a while(true) loop, there is always more queued work, so advanceUntilIdle() never returns and the test hangs indefinitely.

_daily.dev helps developers debugging coroutine test hangs stay ahead of gotchas like this one._

## Similar posts on daily.dev

- [Your ViewModel Tests Shouldn’t Need Android](https://daily.dev/posts/your-viewmodel-tests-shouldn-t-need-android-mcqlipvqw) · ProAndroidDev · 1 upvotes · 1 comments
- [You’re Spawning Too Many Coroutines \(And Your App Is Paying the Price\)](https://daily.dev/posts/you-re-spawning-too-many-coroutines-and-your-app-is-paying-the-price--cnpg6wg9f) · ProAndroidDev · 1 upvotes · 1 comments

---

Tags: [#testing](https://daily.dev/tags/testing), [#android](https://daily.dev/tags/android), [#kotlin](https://daily.dev/tags/kotlin)

[View this post on daily.dev](https://daily.dev/posts/your-coroutine-tests-are-flaky-because-you-have-two-clocks-running-nwzhmolh7)
