https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
s

sushma nayak

03/25/2021, 6:55 PM
I have a function something like
Copy code
suspend fun <T : Any> request(target: APITarget, responseDeserializer: DeserializationStrategy<T>, response: (NetworkResult) -> Unit): Cancelable
How do I test this? Wait till the response lamda completes and cross verify the result. Putting the test inside runblocking doesn’t work.
b

Benoît

03/25/2021, 7:16 PM
When testing stuff like that I know a hacky way that works most of the time. If you use this class
Copy code
class CoroutineLock() {
    private var channel by AtomicReferenceDelegate<ConflatedBroadcastChannel<Unit>?>(null)

    private val mutex = Mutex()
    val isLocked: Boolean get() = channel != null

    suspend fun lock() {
        mutex.withLock {
            val channel = channel ?: ConflatedBroadcastChannel()
            this.channel = channel
            channel.openSubscription().receive()
        }
    }

    fun unlock() {
        channel?.offer(Unit)
        channel = null
    }
}
With the AtomicReferenceDelegate being a simple ReadWriteProperty around AtomicReference to avoid mutation crashes on native. It works like the JVM
wait()
and
notify()
functions on Object. You can use this to synchronise your code the way you need to
a

araqnid

03/25/2021, 7:39 PM
Would have thought a
CompletableDeferred<NetworkResult>
was more appropriate:
Copy code
val result = CompletableDeferred<NetworkResult>()
launch { request(target, deser) { result.complete(it) } }
result.await()
something smells about having a suspend function that takes a result-emitting callback and returns a cancellation handle though. shouldn’t it just be returning NetworkResult and registering its cancellation handle with the coroutine context?
b

Benoît

03/25/2021, 7:58 PM
I agree a CompletableDeferred would be a better option
s

sushma nayak

03/25/2021, 7:58 PM
Yeah, Could be a wrong approach. I’m new to kotlin and kmm. Open to learning it correct way. I understand how suspend functions can return the result directly. But I don’t understand how to “registering its cancellation handle with the coroutine context?” Would be very grateful if you could point be towards an example. Basically these are network requests and I would like to have the ability to cancel them. @araqnid
a

araqnid

03/25/2021, 8:42 PM
basically, if you call
supendCancellableCoroutine
then execution is suspended, and you’re given a continuation to hook up to the callback, or call
cancel()
on
You can also do
cont.invokeOnCancellation { }
to propagate a cancellation of the coroutine context to the Cancelable
the docs for
suspendCancellableCoroutine
are a good place to look
b

Benoît

03/25/2021, 9:46 PM
Also make sure you check for cancellation @sushma nayak, you don't do it in your example @araqnid, it might not be important for your use case but it could be for others
s

sushma nayak

03/26/2021, 7:48 AM
suspendCancellableCoroutine
is \m/ It seems to be working. Thank you @Benoît and @araqnid 😄 People like you in the community make newbies like me survive in the platform. Could otherwise drive us away with frustration.
🎉 1
b

Benoît

03/26/2021, 9:35 AM
Glad you figured it out. And no worries, we're all someone's noob here :)