From 8b16a5aabcdac5057b3ef75c68cfe0c82d2d9ab9 Mon Sep 17 00:00:00 2001 From: nappy29 Date: Sat, 26 Oct 2024 07:58:53 +0100 Subject: [PATCH 1/8] Added unit tests --- core-kotlin-modules/core-kotlin-flows/pom.xml | 14 +++ .../com/baeldung/flowTest/FlowTestUnitTest.kt | 108 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-flows/pom.xml b/core-kotlin-modules/core-kotlin-flows/pom.xml index 5c49cfd7b..900dfbb5e 100644 --- a/core-kotlin-modules/core-kotlin-flows/pom.xml +++ b/core-kotlin-modules/core-kotlin-flows/pom.xml @@ -32,6 +32,20 @@ 3.4.11 + + org.jetbrains.kotlinx + kotlinx-coroutines-core + 1.6.0 + + + + + org.jetbrains.kotlinx + kotlinx-coroutines-test + 1.6.0 + test + + diff --git a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt new file mode 100644 index 000000000..ed4246164 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt @@ -0,0 +1,108 @@ +package com.baeldung.flowTest + +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runBlockingTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import kotlin.test.DefaultAsserter.fail + +class FlowTestUnitTest { + + @Test + fun `simpleFlow should emit 1 2 3`() = runBlockingTest { + val flow = simpleFlow().toList() + + assertEquals(listOf(1, 2, 3), flow) + } + + @Test + fun `transformedFlow should multiply values by 2`() = runBlockingTest { + val result = transformedFlow().toList() + assertEquals(listOf(2, 4, 6), result) + } + + @Test + fun `errorFlow should throw Test Exception`() = runBlockingTest { + val flow = errorFlow() + + try { + flow.collect {} + fail("Expected an exception") + } catch (e: Exception) { + assertEquals("Test Exception", e.message) + } + } + + @Test + fun `cancellableFlow should stop after cancellation`() = runBlockingTest { + val emittedValues = mutableListOf() + + val job = launch { + cancellableFlow().collect { + emittedValues.add(it) + if (it == 2) cancel() + } + } + job.join() + + assertEquals(listOf(0, 1, 2), emittedValues) + } + + @Test + fun `delayedFlow should handle delayed emissions`() = runBlockingTest { + val result = delayedFlow().toList() + assertEquals(listOf(1, 2), result) + } + + @Test + fun `counterStateFlow should increment correctly`() = runBlockingTest { + incrementCounter() + assertEquals(1, counterStateFlow.value) + + incrementCounter() + assertEquals(2, counterStateFlow.value) + } + +} + +fun simpleFlow(): Flow = flow { + emit(1) + emit(2) + emit(3) +} + +fun transformedFlow(): Flow = flow { + emit(1) + emit(2) + emit(3) +}.map { it * 2 } + +fun errorFlow(): Flow = flow { + emit(1) + throw Exception("Test Exception") +} + +fun cancellableFlow(): Flow = flow { + repeat(5) { + emit(it) + delay(1000) + } +} + +fun delayedFlow(): Flow = flow { + delay(500) + emit(1) + delay(500) + emit(2) +} + +val counterStateFlow = MutableStateFlow(0) + +fun incrementCounter() { + counterStateFlow.value++ +} + + From 48bcbbe2560aa1e21770b3fa10c6389b14d45e37 Mon Sep 17 00:00:00 2001 From: nappy29 Date: Thu, 31 Oct 2024 22:20:15 +0100 Subject: [PATCH 2/8] changes to code --- .../com/baeldung/flowTest/FlowTestUnitTest.kt | 39 ++++++------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt index ed4246164..5b6f1ea56 100644 --- a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt +++ b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt @@ -4,40 +4,39 @@ import kotlinx.coroutines.cancel import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import kotlin.test.DefaultAsserter.fail +import org.junit.jupiter.api.assertThrows class FlowTestUnitTest { @Test - fun `simpleFlow should emit 1 2 3`() = runBlockingTest { + fun `simpleFlow should emit 1 2 3`() = runTest { val flow = simpleFlow().toList() assertEquals(listOf(1, 2, 3), flow) } @Test - fun `transformedFlow should multiply values by 2`() = runBlockingTest { + fun `transformedFlow should multiply values by 2`() = runTest { val result = transformedFlow().toList() assertEquals(listOf(2, 4, 6), result) } @Test - fun `errorFlow should throw Test Exception`() = runBlockingTest { + fun `errorFlow should throw Test Exception`() = runTest { val flow = errorFlow() - try { - flow.collect {} - fail("Expected an exception") - } catch (e: Exception) { - assertEquals("Test Exception", e.message) + val exception = assertThrows { + flow.collect() } + assertEquals("Test Exception", exception.message) + } @Test - fun `cancellableFlow should stop after cancellation`() = runBlockingTest { + fun `cancellableFlow should stop after cancellation`() = runTest { val emittedValues = mutableListOf() val job = launch { @@ -52,20 +51,10 @@ class FlowTestUnitTest { } @Test - fun `delayedFlow should handle delayed emissions`() = runBlockingTest { + fun `delayedFlow should handle delayed emissions`() = runTest { val result = delayedFlow().toList() assertEquals(listOf(1, 2), result) } - - @Test - fun `counterStateFlow should increment correctly`() = runBlockingTest { - incrementCounter() - assertEquals(1, counterStateFlow.value) - - incrementCounter() - assertEquals(2, counterStateFlow.value) - } - } fun simpleFlow(): Flow = flow { @@ -99,10 +88,4 @@ fun delayedFlow(): Flow = flow { emit(2) } -val counterStateFlow = MutableStateFlow(0) - -fun incrementCounter() { - counterStateFlow.value++ -} - From e1337e00f7c03414658d270df928bacccdbc7eaa Mon Sep 17 00:00:00 2001 From: nappy29 Date: Tue, 5 Nov 2024 10:07:31 +0100 Subject: [PATCH 3/8] code changes --- .../com/baeldung/flowTest/FlowTestUnitTest.kt | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt index 5b6f1ea56..55cc110c5 100644 --- a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt +++ b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt @@ -1,9 +1,11 @@ package com.baeldung.flowTest import kotlinx.coroutines.cancel +import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch +import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test @@ -28,26 +30,27 @@ class FlowTestUnitTest { fun `errorFlow should throw Test Exception`() = runTest { val flow = errorFlow() + val emittedValues = mutableListOf() val exception = assertThrows { - flow.collect() + flow.collect { emittedValues.add(it) } } + + assertEquals(listOf(1, 2), emittedValues) assertEquals("Test Exception", exception.message) } @Test - fun `cancellableFlow should stop after cancellation`() = runTest { + fun `cancellableFlow stops emitting after external cancellation`() = runTest { val emittedValues = mutableListOf() - val job = launch { - cancellableFlow().collect { - emittedValues.add(it) - if (it == 2) cancel() - } + cancellableFlow().collect { emittedValues.add(it) } } - job.join() - assertEquals(listOf(0, 1, 2), emittedValues) + advanceTimeBy(2000) + job.cancelAndJoin() + + assertEquals(listOf(0, 1), emittedValues) } @Test @@ -71,6 +74,7 @@ fun transformedFlow(): Flow = flow { fun errorFlow(): Flow = flow { emit(1) + emit(2) throw Exception("Test Exception") } From 8a816fd8114533bc3ce6ca76b269bbf2bd158056 Mon Sep 17 00:00:00 2001 From: nappy29 Date: Mon, 18 Nov 2024 12:22:50 +0100 Subject: [PATCH 4/8] code fixes --- core-kotlin-modules/core-kotlin-flows/pom.xml | 16 ++++----- .../com/baeldung/flowTest/FlowTestUnitTest.kt | 33 +++++++++++-------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/core-kotlin-modules/core-kotlin-flows/pom.xml b/core-kotlin-modules/core-kotlin-flows/pom.xml index 900dfbb5e..62dbead56 100644 --- a/core-kotlin-modules/core-kotlin-flows/pom.xml +++ b/core-kotlin-modules/core-kotlin-flows/pom.xml @@ -18,38 +18,36 @@ ${junit.version} - - org.jetbrains.kotlinx kotlinx-coroutines-reactor - 1.6.0 + ${kotlinx.coroutines.version} io.projectreactor reactor-core - 3.4.11 + ${reactor.version} org.jetbrains.kotlinx kotlinx-coroutines-core - 1.6.0 + ${kotlinx.coroutines.version} - org.jetbrains.kotlinx kotlinx-coroutines-test - 1.6.0 + ${kotlinx.coroutines.version} test - 4.13.2 + 1.7.3 + 3.4.11 - + diff --git a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt index 55cc110c5..040d85e5c 100644 --- a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt +++ b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import java.util.concurrent.CancellationException class FlowTestUnitTest { @@ -27,17 +28,10 @@ class FlowTestUnitTest { } @Test - fun `errorFlow should throw Test Exception`() = runTest { - val flow = errorFlow() - - val emittedValues = mutableListOf() - val exception = assertThrows { - flow.collect { emittedValues.add(it) } - } - - assertEquals(listOf(1, 2), emittedValues) - assertEquals("Test Exception", exception.message) + fun `errorFlow should emit values and recover from exception`() = runTest { + val emittedValues = errorFlow().toList() + assertEquals(listOf(1, 2, -1), emittedValues) } @Test @@ -76,12 +70,25 @@ fun errorFlow(): Flow = flow { emit(1) emit(2) throw Exception("Test Exception") +}.catch { e -> + emit(-1) } fun cancellableFlow(): Flow = flow { - repeat(5) { - emit(it) - delay(1000) + try { + repeat(5) { + emit(it) + delay(1000) + } + } finally { + println("Cleanup: Emitting -1") + emit(-1) + } +}.onEach { value -> + if (value == 2) throw CancellationException("Flow was canceled at value 2") +}.onCompletion { cause -> + if (cause is CancellationException) { + println("Flow canceled: Releasing resources") } } From 578025ca1d64e1ede041957b162c71600146cea4 Mon Sep 17 00:00:00 2001 From: nappy29 Date: Mon, 18 Nov 2024 12:32:36 +0100 Subject: [PATCH 5/8] code fixes --- .../kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt index 040d85e5c..80723fc51 100644 --- a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt +++ b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt @@ -14,12 +14,12 @@ import java.util.concurrent.CancellationException class FlowTestUnitTest { - @Test - fun `simpleFlow should emit 1 2 3`() = runTest { - val flow = simpleFlow().toList() + @Test + fun `simpleFlow should emit 1 2 3`() = runTest { + val flow = simpleFlow().toList() - assertEquals(listOf(1, 2, 3), flow) - } + assertEquals(listOf(1, 2, 3), flow) + } @Test fun `transformedFlow should multiply values by 2`() = runTest { From c8f6e89a39b048d8770290874715a7b387f71e2c Mon Sep 17 00:00:00 2001 From: nappy29 Date: Mon, 25 Nov 2024 10:40:41 +0100 Subject: [PATCH 6/8] code fixes --- .../com/baeldung/flowTest/FlowTestUnitTest.kt | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt index 80723fc51..c21efa8e6 100644 --- a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt +++ b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt @@ -1,10 +1,7 @@ package com.baeldung.flowTest -import kotlinx.coroutines.cancel -import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.delay +import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals @@ -34,6 +31,19 @@ class FlowTestUnitTest { assertEquals(listOf(1, 2, -1), emittedValues) } + @Test + fun `implicitCancellationFlow stops on cancellation`() = runTest { + val emittedValues = mutableListOf() + val job = launch { + implicitCancellationFlow().collect { emittedValues.add(it) } + } + + advanceTimeBy(600) + job.cancelAndJoin() + + assertEquals(listOf(1,2), emittedValues) + } + @Test fun `cancellableFlow stops emitting after external cancellation`() = runTest { val emittedValues = mutableListOf() @@ -47,6 +57,19 @@ class FlowTestUnitTest { assertEquals(listOf(0, 1), emittedValues) } + @Test + fun `uncancellableFlow ensures cleanup occurs`() = runTest { + val emittedValues = mutableListOf() + val job = launch { + uncancellableFlow().collect { emittedValues.add(it) } + } + + advanceTimeBy(600) + job.cancelAndJoin() + + assertEquals(listOf(1, -1), emittedValues) + } + @Test fun `delayedFlow should handle delayed emissions`() = runTest { val result = delayedFlow().toList() @@ -99,4 +122,23 @@ fun delayedFlow(): Flow = flow { emit(2) } +fun implicitCancellationFlow(): Flow = flow { + emit(1) + delay(500) + emit(2) + delay(500) + emit(3) +} +fun uncancellableFlow(): Flow = flow { + try { + emit(1) + delay(500) + emit(2) + } finally { + withContext(NonCancellable) { + println("Releasing resources") + emit(-1) + } + } +} From 41cc8134aa18412e3171424558e9842d84dd8b03 Mon Sep 17 00:00:00 2001 From: nappy29 Date: Mon, 25 Nov 2024 11:37:38 +0100 Subject: [PATCH 7/8] Added code --- .../test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt index c21efa8e6..969da908f 100644 --- a/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt +++ b/core-kotlin-modules/core-kotlin-flows/src/test/kotlin/com/baeldung/flowTest/FlowTestUnitTest.kt @@ -1,6 +1,7 @@ package com.baeldung.flowTest import kotlinx.coroutines.* +import kotlinx.coroutines.channels.onFailure import kotlinx.coroutines.flow.* import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest @@ -64,10 +65,10 @@ class FlowTestUnitTest { uncancellableFlow().collect { emittedValues.add(it) } } - advanceTimeBy(600) + advanceTimeBy(400) job.cancelAndJoin() - assertEquals(listOf(1, -1), emittedValues) + assertEquals(listOf(1), emittedValues) } @Test @@ -138,7 +139,6 @@ fun uncancellableFlow(): Flow = flow { } finally { withContext(NonCancellable) { println("Releasing resources") - emit(-1) } } } From 070de0042704ed5e1ca035b9bf80e54b2d3f41b2 Mon Sep 17 00:00:00 2001 From: nappy29 Date: Thu, 28 Nov 2024 13:58:27 +0100 Subject: [PATCH 8/8] fixes --- core-kotlin-modules/core-kotlin-flows/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/core-kotlin-modules/core-kotlin-flows/pom.xml b/core-kotlin-modules/core-kotlin-flows/pom.xml index 62dbead56..b72af1208 100644 --- a/core-kotlin-modules/core-kotlin-flows/pom.xml +++ b/core-kotlin-modules/core-kotlin-flows/pom.xml @@ -4,7 +4,6 @@ core-kotlin-flows core-kotlin-flows jar - com.baeldung core-kotlin-modules