#kotlin #kotlin-coroutines #ktor
#kotlin #kotlin-сопрограммы #ktor
Вопрос:
Я пытаюсь написать мультиплатформенную библиотеку kotlin (Android и ios), которая использует ktor. Таким образом, у меня возникают некоторые проблемы с сопрограммами kotlin:
When writing tests I always get kotlinx.coroutines.JobCancellationException: Parent job is Completed; job=JobImpl{Completed}@... exception.
Я использую движок ktors для своих тестов:
client = HttpClient(MockEngine)
{
engine
{
addHandler
{ request ->
// Create response object
}
}
}
Примерный метод (модуль commonMain) с использованием ktor. Все методы в моей библиотеке написаны аналогичным образом. Исключение возникает, если вызывается client.get .
suspend fun getData(): Either<Exception, String> = coroutineScope
{
// Exception occurs in this line:
val response: HttpResponse = client.get { url("https://www.google.com") }
return if (response.status == HttpStatusCode.OK)
{
(response.readText() as T).right()
}
else
{
Exception("Error").left()
}
}
Пример модульного теста (модуль commonTest) для вышеуказанного метода. Оператор assertTrue никогда не вызывается, поскольку исключение генерируется ранее.
@Test
fun getDataTest() = runTest
{
val result = getData()
assertTrue(result.isRight())
}
Фактическая реализация runTest в модулях androidTest и iosTest.
actual fun<T> runTest(block: suspend () -> T) { runBlocking { block() } }
Я думал, что когда я использую CoroutineScope, он ждет, пока не будут выполнены все дочерние сопрограммы. Что я делаю не так и как я могу исправить это исключение?
Комментарии:
1. Вы нашли решение?
2. область действия сопрограммы, насколько я знаю, отменит другие сопрограммы. Если вы хотите отделить родительское задание от других заданий, вы можете использовать CoroutineScope.launch или вызвать call с областью действия супервизора
Ответ №1:
вы не можете кэшировать HttpClient ИТ-директора в переменной клиента и повторно использовать, было бы лучше, если бы изменить следующий код в вашей реализации.
val client:HttpClient get() = HttpClient(MockEngine) {
engine {
addHandler { request ->
// Create response object
}
}
}
Комментарии:
1. Не ясно. Предоставьте дополнительную информацию
2. Комментарий означает, что если вы сохраните HttpClient в val, например, val client:HttpClient get() = HttpClient(Android), это также может привести к исключению JobCancellationException. Однако, если вы возвращаете новый экземпляр клиента каждый раз, когда получаете доступ к значению (это было get()) ), проблема исчезнет. По крайней мере, моя проблема может быть решена с помощью этого незначительного изменения.
Ответ №2:
Библиотека должна быть обновлена, этот сбой находится в отчете об исправлении здесь: https://newreleases.io/project/github/ktorio/ktor/release/1.6.1
Комментарии:
1. Определенно исправил это для меня, начиная с версии 1.5.2
2. Рад помочь, приятель
Ответ №3:
Проблема в том, что вы не можете использовать один и тот же экземпляр HttpClient. Мой ej:
HttpClient(CIO) {
install(JsonFeature) {
serializer = GsonSerializer()
}
}.use { client ->
return@use client.request("URL") {
method = HttpMethod.Get
}
}