rsetkus
02/18/2021, 12:43 PM@Test
fun testSuccess() = runBlocking {
val repository = Repository()
var actual: String? = null
val job = repository.getData(TEST_URL) {
actual = it
}
job.join()
assertEquals(TEST_MESSAGE, actual)
}
Repository getData function:
fun getData(
url: String,
callback: (String) -> Unit = {}
): Job {
return GlobalScope.launch(dispatcher) { // Dispatchers.Main (Android), NsQueueDispatcher (iOS)
try {
val message: String = httpClient.request(...)
callback(message)
} catch (e: Exception) {
println("Exception: $e")
}
}
}
Test passes running for Android platform but getting infinite loop for iOS platform. Does anybody know a good way to test a callback function which was invoked within coroutine? Any help much appreciated. 🙏🏻uli
02/18/2021, 4:02 PMhttpClient.request()
call start? does it return?rsetkus
02/18/2021, 5:31 PMgetData
is a function which is used directly in client platforms (Android & iOS). Don’t want to expose coroutines for various reasons: a) don’t want to dictate technology to be used b) although Kotlin Coroutines is supported in Objective-C but it is very experimental and suspend
functions compiles/generates as with callback functions anyway.
Seems that it is getting stuck when launching a coroutine. Cannot get anything printed inside launch
lambda.uli
02/18/2021, 5:43 PMNsQueueDispatcher(dispatch_get_main_queue())
?rsetkus
02/18/2021, 5:50 PMactual val dispatcher: CoroutineDispatcher = NsQueueDispatcher(dispatch_get_main_queue())
internal class NsQueueDispatcher(private val dispatchQueue: dispatch_queue_t) : CoroutineDispatcher() {
override fun dispatch(context: CoroutineContext, block: Runnable) {
dispatch_async(dispatchQueue.freeze()) {
block.run()
}
}
}
uli
02/18/2021, 5:51 PMrunBlocking
?dispatch_async
rsetkus
02/18/2021, 5:57 PMrunningBlock
keeps blocking coroutines dispatcher for iOS.runBlocking
but then Android tests broken.
Cannot find any good examples online which would match my case.uli
02/18/2021, 6:16 PMrsetkus
02/18/2021, 6:39 PMuli
02/18/2021, 7:46 PMrsetkus
02/18/2021, 9:43 PMExecutors.newSingleThreadExecutor().asCoroutineDispatcher()
but this not possible in Kotlin Multiplatform.uli
02/18/2021, 9:53 PMrsetkus
02/18/2021, 10:06 PMdispatch_queue_serial_t
instead of dispatch_queue_t
? Sorry, I am Android/Kotlin developer. Not very familiar with Native/iOS.uli
02/18/2021, 10:30 PMrsetkus
02/18/2021, 10:50 PMuli
02/18/2021, 10:57 PMNsQueueDispatcher(DispatchQueue())
. Not exactly sure about the syntaxrsetkus
02/18/2021, 11:06 PMuli
02/19/2021, 10:19 AMfun getData(
url: String,
callback: (String) -> Unit = {}
): Job {
return GlobalScope.launch(testContext) { // Dispatchers.Main (Android), NsQueueDispatcher (iOS)
try {
val message: String = url
callback(message)
} catch (e: Exception) {
println("Exception: $e")
}
}
}
@Test
fun testSuccess() = runBlocking(testContext) {
var actual: String? = null
val job = getData("OK") {
actual = it
}
job.join()
assertEquals("OK", actual)
}
Works fine on my machinersetkus
02/19/2021, 11:24 AMuli
02/19/2021, 11:26 AMval message: String = url
delay(100)
callback(message)
rsetkus
02/19/2021, 11:47 AMgetData
function suspendable but I think hiding details of implementation is a way to go in my case.