I have a coroutine function that runs infinitely and makes an API call every 8 seconds. I am trying to test it but something feels wrong. Here is the code:
class RefreshStocksUseCaseImpl(
private val dispatcherProvider: DispatcherProvider,
private val stocksRepository: StocksRepository
) : RefreshStocksUseCase {
override suspend fun invoke() {
withContext(dispatcherProvider.io) {
try {
while (true) {
stocksRepository.refreshStocks()
delay(THRESHOLD)
}
} catch (t: Throwable) {
// We could make some extra handling here.
throw t
}
}
}
companion object {
private const val THRESHOLD = 8_000L // 8 seconds
}
}
My test looks like that:
@ExperimentalCoroutinesApi
class RefreshStocksUseCaseImplTest {
private lateinit var useCase: RefreshStocksUseCase
private val dispatcherProvider = TestDispatcherProvider()
@MockK
private lateinit var stocksRepository: StocksRepository
@Before
fun setup() {
MockKAnnotations.init(this, relaxUnitFun = false)
useCase = RefreshStocksUseCaseImpl(dispatcherProvider, stocksRepository)
}
@Test
fun `refreshStocks is called again after threshold`() = dispatcherProvider.io.runBlockingTest {
coEvery { stocksRepository.refreshStocks() } just runs
val job = launch {
useCase()
}
advanceTimeBy(8_000)
job.cancel()
coVerify(exactly = 2) { stocksRepository.refreshStocks() }
}
}
Even though it passes, I feel that I am doing something wrong. I feel like pauseDispatcher
should have played some role here... Any improvements are welcome.