Вызов 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
бизнес-логика метода будет правильной, если тест пройден, и вы можете протестировать службу токенов отдельно, возможно, с более сложным интеграционным тестом или с другими макетами, если вы того пожелаете.