CXwudi
10/04/2024, 6:26 PMlabelsChannel()
, I have some improvement idea in the comment sectionCXwudi
10/04/2024, 6:32 PMlabelsChannel()
from runTest
unit test. If I pass the TestScope
instance from runTest
into label channel like:
runTest(testDispatcher) {
val labelsChannel = landingPageStore.labelsChannel(this)
...
}
Then the test will be stuck and never finish.
If I do:
runTest(testDispatcher) {
val separateScope = TestScope(testDispatcher) // separate scope for label channel
val labelsChannel = landingPageStore.labelsChannel(separateScope)
....
separateScope.cancel()
}
Then the test works.CXwudi
10/04/2024, 6:35 PMlabelsChannel()
is creating a coroutine that simply just waiting for cancellation and then call other shutdown hooks.
However, the this
TestScope
from runTest
are not going to be cancelled until all children coroutines are finished. Manually call this.cancel()
in runTest
will also be traded as a test failure. Hence, this creates a deadlock unless a separate coroutine scope is used for the labelsChannel()
CXwudi
10/04/2024, 6:42 PM@ExperimentalMviKotlinApi
fun <Label : Any> Store<*, *, Label>.labelsChannel(
capacity: Int = Channel.BUFFERED,
): ReceiveChannel<Label> {
val channel = Channel<Label>(capacity = capacity)
val disposable = labels(
observer(
onComplete = { channel.close() },
onNext = channel::trySend
)
)
channel.invokeOnClose { disposable.dispose() }
return channel
}
CXwudi
10/04/2024, 6:45 PM@ExperimentalMviKotlinApi
fun <Label : Any> Store<*, *, Label>.labelsChannel(
sendScope: CoroutineScope,
capacity: Int = Channel.BUFFERED,
): ReceiveChannel<Label> {
val channel = Channel<Label>(capacity = capacity)
val disposable = labels(observer(
onComplete = {
channel.close()
},
onNext = {
if (sendScope.isActive) {
sendScope.launch {
channel.send(it)
}
}
}
))
channel.invokeOnClose { disposable.dispose() }
return channel
}
This one simply use channel.send
instead of channel.trySend
, and then a coroutine is required for this send
method.Arkadii Ivanov
10/04/2024, 7:02 PMFlow.shareIn
.
On the other hand, you probably shouldn't pass the scope from runTest
. Usually a TestDispatcher
or Dispatchers.Unconfined
is used for testing.CXwudi
10/04/2024, 9:37 PMCXwudi
10/04/2024, 9:37 PM