Вызов ktor http-клиента асинхронно в функции приостановки

У меня есть следующая функция, которая использует HttpClient ktor. а функция tokenService getAccessToken также использует клиент ktor и извлекает токен.

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

и это мой простой тест

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

теперь тест проходит из-за задержки, задержка дает время для первой выборки токена, но если я удалю задержку, функция addUser будет вызвана без предварительной выборки токена. Мой вопрос: есть ли лучший способ сделать это, чтобы избежать задержки в тестах. Я посмотрел на Kotlin Flows, но не знаю, как это реализовать в моем сценарии. Если бы вы могли указать мне правильное направление, я был бы признателен.

2 ответа

Что делать, если вы измените код следующим образом:

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

С другой стороны, модульный тест не должен выполнять настоящие HTTP-вызовы, и вы бы предпочли использовать mockito или mockk, что, на мой взгляд, лучше для Kotlin.

Ваше здоровье

Это общая проблема модульного тестирования в целом. Подумайте о сценарии, когда вам нужно сделать запрос к базе данных, мы не хотим раскручивать и всю базу данных только для модульного тестирования, что сделало бы тестирование медленным и громоздким. Нам нужна быстрая обратная связь от наших модульных тестов, а не добавление задержек повсюду.

Распространенный подход - использовать имитирующую библиотеку, например или Mockk издеваться над сетевым сервисом (в вашем случае tokenService). Если вы использовали Mockito ссылка, вы можете сделать что-то вроде этого:

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

Таким образом вы могли удалить delay(3000)из вашего модульного теста. Тогда ты узнаешь свой addUser бизнес-логика метода будет правильной, если тест пройден, и вы можете протестировать службу токенов отдельно, возможно, с более сложным интеграционным тестом или с другими макетами, если вы того пожелаете.

Другие вопросы по тегам