7

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.

Miltos
  • 166
  • 3
  • I'm wondering if you ever improved on this code, and how you would handle it using the new test API (not using the deprecated `runBlockingTest`). I'm currently dealing with a very similar situation and my thought was to write the test exactly like you did, but I haven't been able to even make the test succeed – Revolutionair Jul 24 '23 at 09:05
  • Could you share a code snippet? What's the error that you are getting? – Miltos Jul 25 '23 at 10:04
  • I figured out that my problem was a coroutine that was launched on a viewModelScope, so cancelling that made the test work as expected. Thank you though! – Revolutionair Jul 25 '23 at 17:13

0 Answers0