title: How to wait for suspendCoroutine in unit test?
body: <p>I want to write tests for my android application. Sometimes the viewModel executes tasks in the background using Kotlins coroutine launch function. These tasks are executed in the viewModelScope that the androidx.lifecycle library so handily provides. In order to still test these functions, I replaced the default android Dispatchers with Dispatchers.Unconfined, which runs the code synchronously. </p>
  
  <p>At least in most of the cases. When using suspendCoroutine, the Dispatchers.Unconfined will not be suspended and later resumed, but instead will simply return. The documentation of <code>Dispatchers.Unconfined</code> reveals why:</p>
  
  <blockquote>
    <p>[Dispatchers.Unconfined] lets the coroutine resume in whatever thread that is used by the corresponding suspending function.</p>
  </blockquote>
  
  <p>So by my understanding, the coroutine is not actually suspended, but the rest of the async function after <code>suspendCoroutine</code> is run on the thread that calls <code>continuation.resume</code>. Therefore the test fails.</p>
  
  <p>Example:</p>
  
  <pre><code>class TestClassTest {
  var testInstance = TestClass()
  
  @Test
  fun `Test with default dispatchers should fail`() {
      testInstance.runAsync()
      assertFalse(testInstance.valueToModify)
  }
  
  @Test
  fun `Test with dispatchers replaced by Unconfined should pass`() {
      testInstance.DefaultDispatcher = Dispatchers.Unconfined
      testInstance.IODispatcher = Dispatchers.Unconfined
      testInstance.runAsync()
      assertTrue(testInstance.valueToModify)
  }
  
  @Test
  fun `I need to also test some functions that use suspend coroutine - How can I do that?`() {
      testInstance.DefaultDispatcher = Dispatchers.Unconfined
      testInstance.IODispatcher = Dispatchers.Unconfined
      testInstance.runSuspendCoroutine()
      assertTrue(testInstance.valueToModify)//fails
  }
  }
  
  class TestClass {
  var DefaultDispatcher: CoroutineContext = Dispatchers.Default
  var IODispatcher: CoroutineContext = Dispatchers.IO
  val viewModelScope = CoroutineScope(DefaultDispatcher)
  var valueToModify = false
  
  fun runAsync() {
      viewModelScope.launch(DefaultDispatcher) {
          valueToModify = withContext(IODispatcher) {
              sleep(1000)
              true
          }
      }
  }
  
  fun runSuspendCoroutine() {
      viewModelScope.launch(DefaultDispatcher) {
          valueToModify = suspendCoroutine {
              Thread {
                  sleep(1000)
                  //long running operation calls listener from background thread
                  it.resume(true)
              }.start()
          }
      }
  }
  }
  </code></pre>
  
  <p>I was experimenting around with <code>runBlocking</code>, however it only helps if you call launch using the <code>CoroutineScope</code> created by <code>runBlocking</code>. But since my code is launching on the <code>CoroutineScope</code> provided by <code>viewModelScope</code> this will not work. If possible I would prefer not to inject a CoroutineScope everywhere, because any lower level class could (and does) make their own CoroutineScope as in the example, and then the Test has to know a lot about the implementation details. The idea behind the scopes is that every class has control over cancelling their asynchronous operations. The viewModelScope for example is by default cancelled when the viewModel is destroyed.</p>
  
  <p>My question:
  <strong>What coroutine dispatcher could I use that runs launch and withContext etc blocking (like <code>Dispatchers.Unconfined</code>) and also runs suspendCoroutine blocking?</strong></p>