I.S
I.S

Reputation: 2053

Why Unit tests with coroutines delay() fails?

I have this piece of code I do want to test loadSession() and testLoadSession() is testing method I have SuccessActivationCodeRepository for unit test and observeForTesting is extension function you can see I have added longer delay in the unit test but it doesn't help it return null for sessionData, How can I fix this?

fun loadSession(activationCode: ActivationCode) {
    viewModelScope.launch {
      delay(START_DELAY)
      when (val result = activationCodeRepository.fetchSession(activationCode)) {
        is Response.Success<ISession> -> {
          sessionMutableData.postValue(result.data)
        }
        is Response.Failure -> {
          if (result.message == ERROR_RETRY_ACTIVATION) {
            retryActivationMutableData.postValue(true)
          } else {
            errorMessageMutableData.postValue(ConsumableValue(result.message))
          }
        }
      }
    }
  } 


@Test
  fun testLoadSession() {
    viewModel.activationCodeRepository = SuccessActivationCodeRepository()
    val activationCode = ActivationCode()
    val expectedSession = Session("", "", "")
    viewModel.loadSession(activationCode)
    runBlocking {
      delay(10000L)
    }
    viewModel.sessionData.observeForTesting {
     assertThat(viewModel.sessionData.value?.sessionToken).isEqualTo(expectedSession.sessionToken)
    }
  }

class SuccessActivationCodeRepository : IActivationCodeRepository {
  override suspend fun fetchSession(activationCode: ActivationCode): Response<ISession> {
    return Response.Success(Session())
  }
}

fun <T> LiveData<T>.observeForTesting(block: () -> Unit) {
  val observer = Observer<T> { Unit }
  try {
    observeForever(observer)
    block()
  } finally {
    removeObserver(observer)
  }
}

Upvotes: 5

Views: 3187

Answers (1)

I.S
I.S

Reputation: 2053

I have added coroutinesTestRule.testDispatcher.runBlockingTest {} and advanceTimeBy(20000L) and set time bigger than delay time in loadSession()

 @Test
  fun testLoadSession() {
    viewModel.activationCodeRepository = SuccessActivationCodeRepository()
    val activationCode = ActivationCode()
    val expectedSession = Session()
    coroutinesTestRule.testDispatcher.runBlockingTest {
      viewModel.loadSession(activationCode)
      viewModel.sessionData.observeForTesting {
        advanceTimeBy(20000L)
        assertThat(viewModel.sessionData.value.sessionToken).isEqualTo(expectedSession.sessionToken)
      }
    }
  }```

Upvotes: 9

Related Questions