Call ktor http client asynchronously in a suspend function

1.2k Views Asked by At

I have the following function that uses ktor's HttpClient. and the tokenService getAccessToken function also uses ktor client and fetches a token.

suspend fun addUser(user: User): User {
    return client.post("${Base}api/v1/adduser") {
        contentType(ContentType.Application.Json)
        header("Authorization", "Bearer ${tokenService.getAccessToken()}")
        body = user
    }
}

and this is my simple test

@Test
fun `should add user`() = runBlocking {
    delay(3000)
    val user = userService.addUser(User("john doe"))
    user.firstName shouldBe "john doe"
}

now the test passes because of the delay, the delay gives time for the token to be fetched first, but if I remove the delay the addUser function gets called without fetching the token first. My question is, is there a better way to do this, to avoid adding delay to tests. I looked at Kotlin Flows but I don't know how to implement it for my scenario. If you could point me in the right direction I would be grateful.

1

There are 1 best solutions below

0
On

This is a common issue with unit testing in general. Think of the scenario of when you have to make a request to a database, we don't want to spin up and entire database just to unit test that, it would make testing slow and cumbersome. We want fast feedback from our unit tests rather than adding delays everywhere.

A common approach is to use a mocking library like Mockito or Mockk to mock the network service (in your case tokenService). If you used Mockito reference you could do something like this:

val mockTokenService = Mockito.mock(TokenService::class.java)
Mockito.`when`(mockTokenService.getAccessToken()).thenReturn("sampleToken123")

That way you could remove delay(3000) from your unit test. Then you'll know your addUser method business logic will be correct if the test passes, and you can test the token service separately, perhaps with a more-involved integration test or with other mocks if you so choose.