Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using combine() operator with TestCoroutineDispatcher causes test to fail #1742

Closed
ttenushko opened this issue Dec 31, 2019 · 0 comments
Closed
Assignees
Labels

Comments

@ttenushko
Copy link

Kotlin: 1.3.50
Coroutines: 1.3.3

Test failed when using combine operator and TestCoroutineDispatcher (test passed when using Dispatchers.Unconfined)

class FlowCombineTest {

    @Test
    fun doTest() {
        val intProvider = ObservableValue(0)
        val stringProvider = ObservableValue("")
        var data = Pair(0, "")
        val scope = CoroutineScope(TestCoroutineDispatcher() + SupervisorJob()) // test failed, use CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) to pass
        scope.launch {
            combine(
                intProvider.observe(),
                stringProvider.observe()
            ) { intValue, stringValue -> Pair(intValue, stringValue) }
                .collect { pair ->
                    data = pair
                }
        }

        intProvider.set(1)
        stringProvider.set("3")
        intProvider.set(2)
        intProvider.set(3)

        scope.cancel()
        assertEquals("Test failed", Pair(3, "3"), data)
    }

    class ObservableValue<T>(initial: T) {

        var value: T = initial
            private set
        private val listeners = CopyOnWriteArraySet<Listener<T>>()

        fun set(value: T) {
            this.value = value
            listeners.forEach { it.onValueChanged(value) }
        }

        fun addListener(listener: Listener<T>) {
            listeners.add(listener)
        }

        fun removeListener(listener: Listener<T>) {
            listeners.remove(listener)
        }

        interface Listener<T> {
            fun onValueChanged(value: T)
        }
    }

    private fun <T> ObservableValue<T>.observe(): Flow<T> =
        callbackFlow {
            val listener = object : ObservableValue.Listener<T> {
                override fun onValueChanged(value: T) {
                    if (!isClosedForSend) {
                        offer(value)
                    }
                }
            }
            addListener(listener)
            listener.onValueChanged(value)
            awaitClose { removeListener(listener) }
        }
}
@qwwdfsad qwwdfsad added the test label Apr 21, 2020
@qwwdfsad qwwdfsad self-assigned this Apr 21, 2020
dkhalanskyjb added a commit that referenced this issue Nov 1, 2021
Defines two test dispatchers:
* StandardTestDispatcher, which, combined with runTest,
  gives an illusion of an event loop;
* UnconfinedTestDispatcher, which is like
  Dispatchers.Unconfined, but skips delays.

By default, StandardTestDispatcher is used due to the somewhat
chaotic execution order of Dispatchers.Unconfined.
TestCoroutineDispatcher is deprecated.

Fixes #1626
Fixes #1742
Fixes #2082
Fixes #2102
Fixes #2405
Fixes #2462
dkhalanskyjb added a commit that referenced this issue Nov 17, 2021
Defines two test dispatchers:
* StandardTestDispatcher, which, combined with runTest,
  gives an illusion of an event loop;
* UnconfinedTestDispatcher, which is like
  Dispatchers.Unconfined, but skips delays.

By default, StandardTestDispatcher is used due to the somewhat
chaotic execution order of Dispatchers.Unconfined.
TestCoroutineDispatcher is deprecated.

Fixes #1626
Fixes #1742
Fixes #2082
Fixes #2102
Fixes #2405
Fixes #2462
dkhalanskyjb added a commit that referenced this issue Nov 17, 2021
Defines two test dispatchers:
* StandardTestDispatcher, which, combined with runTest,
  gives an illusion of an event loop;
* UnconfinedTestDispatcher, which is like
  Dispatchers.Unconfined, but skips delays.

By default, StandardTestDispatcher is used due to the somewhat
chaotic execution order of Dispatchers.Unconfined.
TestCoroutineDispatcher is deprecated.

Fixes #1626
Fixes #1742
Fixes #2082
Fixes #2102
Fixes #2405
Fixes #2462
dkhalanskyjb added a commit that referenced this issue Nov 19, 2021
Defines two test dispatchers:
* StandardTestDispatcher, which, combined with runTest,
  gives an illusion of an event loop;
* UnconfinedTestDispatcher, which is like
  Dispatchers.Unconfined, but skips delays.

By default, StandardTestDispatcher is used due to the somewhat
chaotic execution order of Dispatchers.Unconfined.
TestCoroutineDispatcher is deprecated.

Fixes #1626
Fixes #1742
Fixes #2082
Fixes #2102
Fixes #2405
Fixes #2462
yorickhenning pushed a commit to yorickhenning/kotlinx.coroutines that referenced this issue Jan 28, 2022
This commit introduces the new version of the test module.
Please see README.md and MIGRATION.md for a thorough
discussion of the changes.

Fixes Kotlin#1203
Fixes Kotlin#1609
Fixes Kotlin#2379
Fixes Kotlin#1749
Fixes Kotlin#1204
Fixes Kotlin#1390
Fixes Kotlin#1222
Fixes Kotlin#1395
Fixes Kotlin#1881
Fixes Kotlin#1910
Fixes Kotlin#1772
Fixes Kotlin#1626
Fixes Kotlin#1742
Fixes Kotlin#2082
Fixes Kotlin#2102
Fixes Kotlin#2405
Fixes Kotlin#2462

Co-authored-by: Vsevolod Tolstopyatov <qwwdfsad@gmail.com>
pablobaxter pushed a commit to pablobaxter/kotlinx.coroutines that referenced this issue Sep 14, 2022
This commit introduces the new version of the test module.
Please see README.md and MIGRATION.md for a thorough
discussion of the changes.

Fixes Kotlin#1203
Fixes Kotlin#1609
Fixes Kotlin#2379
Fixes Kotlin#1749
Fixes Kotlin#1204
Fixes Kotlin#1390
Fixes Kotlin#1222
Fixes Kotlin#1395
Fixes Kotlin#1881
Fixes Kotlin#1910
Fixes Kotlin#1772
Fixes Kotlin#1626
Fixes Kotlin#1742
Fixes Kotlin#2082
Fixes Kotlin#2102
Fixes Kotlin#2405
Fixes Kotlin#2462

Co-authored-by: Vsevolod Tolstopyatov <qwwdfsad@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants