From bb5437d0064bde2d879d5fc7dc8184511e026b50 Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Fri, 7 Aug 2020 22:52:18 +0300 Subject: [PATCH 1/3] Add Completable.testAwait() testing function --- reaktive-testing/api/reaktive-testing.api | 4 +++ .../reaktive/test/completable/TestAwait.kt | 32 ++++++++++++++++++ .../test/completable/TestAwaitTest.kt | 33 +++++++++++++++++++ .../reaktive/test/completable/TestAwait.kt | 8 +++++ .../reaktive/test/completable/TestAwait.kt | 8 +++++ 5 files changed, 85 insertions(+) create mode 100644 reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt create mode 100644 reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt create mode 100644 reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt create mode 100644 reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt diff --git a/reaktive-testing/api/reaktive-testing.api b/reaktive-testing/api/reaktive-testing.api index 6c8332102..840a84c31 100644 --- a/reaktive-testing/api/reaktive-testing.api +++ b/reaktive-testing/api/reaktive-testing.api @@ -48,6 +48,10 @@ public final class com/badoo/reaktive/test/completable/DefaultCompletableObserve public static fun onSubscribe (Lcom/badoo/reaktive/test/completable/DefaultCompletableObserver;Lcom/badoo/reaktive/disposable/Disposable;)V } +public final class com/badoo/reaktive/test/completable/TestAwaitKt { + public static final fun testAwait (Lcom/badoo/reaktive/completable/Completable;)V +} + public final class com/badoo/reaktive/test/completable/TestCompletable : com/badoo/reaktive/test/base/TestSource, com/badoo/reaktive/completable/Completable, com/badoo/reaktive/completable/CompletableCallbacks { public fun ()V public fun (Z)V diff --git a/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt b/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt new file mode 100644 index 000000000..bc6fee085 --- /dev/null +++ b/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt @@ -0,0 +1,32 @@ +package com.badoo.reaktive.test.completable + +import com.badoo.reaktive.completable.Completable +import com.badoo.reaktive.completable.blockingAwait + +/** + * This method is used when you need to wait for an asynchronous operation to finish + * and you can't use or don't want to use the [TestScheduler][com.badoo.reaktive.test.scheduler.TestScheduler]. + * + * It is JavaScript friendly, it returns `Promise` which is when returned from a test method + * causes the test to wait for completion. In all other targets [Completable.blockingAwait()][blockingAwait] is used. + * + * Example: + * ``` + * class Calculator { + * fun sum(a: Int, b: Int): Single = + * singleFromFunction { a + b } + * .subscribeOn(computationScheduler) + * } + * + * class CalculatorTest { + * @Test + * fun sum_2_3_returns_5() = + * Calculator() + * .sum(2, 3) + * .doOnBeforeSuccess { assertEquals(6, it) } + * .asCompletable() + * .testAwait() + * } + * ``` + */ +expect fun Completable.testAwait() diff --git a/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt b/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt new file mode 100644 index 000000000..fdcca0270 --- /dev/null +++ b/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt @@ -0,0 +1,33 @@ +package com.badoo.reaktive.test.completable + +import com.badoo.reaktive.completable.completableFromFunction +import com.badoo.reaktive.completable.completableOfEmpty +import com.badoo.reaktive.completable.completableOfError +import com.badoo.reaktive.completable.onErrorResumeNext +import com.badoo.reaktive.completable.subscribeOn +import com.badoo.reaktive.scheduler.computationScheduler +import kotlin.test.Test +import kotlin.test.assertSame + +class TestAwaitTest { + + @Test + fun awaits_success() = + completableOfEmpty() + .subscribeOn(computationScheduler) + .testAwait() + + @Test + fun awaits_error() { + val error = Exception() + + return completableOfError(error) + .subscribeOn(computationScheduler) + .onErrorResumeNext { + completableFromFunction { + assertSame(error, it) + } + } + .testAwait() + } +} diff --git a/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt b/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt new file mode 100644 index 000000000..86a3483cf --- /dev/null +++ b/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt @@ -0,0 +1,8 @@ +package com.badoo.reaktive.test.completable + +import com.badoo.reaktive.completable.Completable +import com.badoo.reaktive.completable.asSingle +import com.badoo.reaktive.single.asPromise + +actual fun Completable.testAwait(): dynamic = + asSingle(Unit).asPromise() diff --git a/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt b/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt new file mode 100644 index 000000000..c05e32a74 --- /dev/null +++ b/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt @@ -0,0 +1,8 @@ +package com.badoo.reaktive.test.completable + +import com.badoo.reaktive.completable.Completable +import com.badoo.reaktive.completable.blockingAwait + +actual fun Completable.testAwait() { + blockingAwait() +} From 5f22ad98022de3d24545fa7e7b93a058d335ea84 Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Mon, 10 Aug 2020 17:08:06 +0300 Subject: [PATCH 2/3] Correct spelling --- .../kotlin/com/badoo/reaktive/test/completable/TestAwait.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt b/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt index bc6fee085..30883c9ae 100644 --- a/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt +++ b/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt @@ -7,7 +7,7 @@ import com.badoo.reaktive.completable.blockingAwait * This method is used when you need to wait for an asynchronous operation to finish * and you can't use or don't want to use the [TestScheduler][com.badoo.reaktive.test.scheduler.TestScheduler]. * - * It is JavaScript friendly, it returns `Promise` which is when returned from a test method + * It is JavaScript friendly, it returns `Promise` which, when returned from a test method, * causes the test to wait for completion. In all other targets [Completable.blockingAwait()][blockingAwait] is used. * * Example: From 3d5f3d79b5803d3bb01f5c7c476a60e387ca74eb Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Tue, 11 Aug 2020 00:00:03 +0300 Subject: [PATCH 3/3] Replace Completable.testAwait with Single.testAwait, add assert callbacks --- reaktive-testing/api/reaktive-testing.api | 9 ++-- .../reaktive/test/completable/TestAwait.kt | 32 ----------- .../badoo/reaktive/test/single/TestAwait.kt | 53 +++++++++++++++++++ .../test/completable/TestAwaitTest.kt | 33 ------------ .../reaktive/test/single/TestAwaitTest.kt | 28 ++++++++++ .../reaktive/test/completable/TestAwait.kt | 8 --- .../badoo/reaktive/test/single/TestAwait.kt | 28 ++++++++++ .../reaktive/test/completable/TestAwait.kt | 8 --- .../badoo/reaktive/test/single/TestAwait.kt | 20 +++++++ 9 files changed, 134 insertions(+), 85 deletions(-) delete mode 100644 reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt create mode 100644 reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt delete mode 100644 reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt create mode 100644 reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/single/TestAwaitTest.kt delete mode 100644 reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt create mode 100644 reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt delete mode 100644 reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt create mode 100644 reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt diff --git a/reaktive-testing/api/reaktive-testing.api b/reaktive-testing/api/reaktive-testing.api index 840a84c31..a114fc648 100644 --- a/reaktive-testing/api/reaktive-testing.api +++ b/reaktive-testing/api/reaktive-testing.api @@ -48,10 +48,6 @@ public final class com/badoo/reaktive/test/completable/DefaultCompletableObserve public static fun onSubscribe (Lcom/badoo/reaktive/test/completable/DefaultCompletableObserver;Lcom/badoo/reaktive/disposable/Disposable;)V } -public final class com/badoo/reaktive/test/completable/TestAwaitKt { - public static final fun testAwait (Lcom/badoo/reaktive/completable/Completable;)V -} - public final class com/badoo/reaktive/test/completable/TestCompletable : com/badoo/reaktive/test/base/TestSource, com/badoo/reaktive/completable/Completable, com/badoo/reaktive/completable/CompletableCallbacks { public fun ()V public fun (Z)V @@ -201,6 +197,11 @@ public final class com/badoo/reaktive/test/single/DefaultSingleObserver$DefaultI public static fun onSuccess (Lcom/badoo/reaktive/test/single/DefaultSingleObserver;Ljava/lang/Object;)V } +public final class com/badoo/reaktive/test/single/TestAwaitKt { + public static final fun testAwait (Lcom/badoo/reaktive/single/Single;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun testAwait$default (Lcom/badoo/reaktive/single/Single;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V +} + public final class com/badoo/reaktive/test/single/TestSingle : com/badoo/reaktive/test/base/TestSource, com/badoo/reaktive/single/Single, com/badoo/reaktive/single/SingleCallbacks { public fun ()V public fun (Z)V diff --git a/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt b/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt deleted file mode 100644 index 30883c9ae..000000000 --- a/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.badoo.reaktive.test.completable - -import com.badoo.reaktive.completable.Completable -import com.badoo.reaktive.completable.blockingAwait - -/** - * This method is used when you need to wait for an asynchronous operation to finish - * and you can't use or don't want to use the [TestScheduler][com.badoo.reaktive.test.scheduler.TestScheduler]. - * - * It is JavaScript friendly, it returns `Promise` which, when returned from a test method, - * causes the test to wait for completion. In all other targets [Completable.blockingAwait()][blockingAwait] is used. - * - * Example: - * ``` - * class Calculator { - * fun sum(a: Int, b: Int): Single = - * singleFromFunction { a + b } - * .subscribeOn(computationScheduler) - * } - * - * class CalculatorTest { - * @Test - * fun sum_2_3_returns_5() = - * Calculator() - * .sum(2, 3) - * .doOnBeforeSuccess { assertEquals(6, it) } - * .asCompletable() - * .testAwait() - * } - * ``` - */ -expect fun Completable.testAwait() diff --git a/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt b/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt new file mode 100644 index 000000000..c0d0c36ab --- /dev/null +++ b/reaktive-testing/src/commonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt @@ -0,0 +1,53 @@ +package com.badoo.reaktive.test.single + +import com.badoo.reaktive.completable.blockingAwait +import com.badoo.reaktive.single.Single + +/** + * This method is used when you need to wait for an asynchronous operation to finish + * and you can't use or don't want to use the [TestScheduler][com.badoo.reaktive.test.scheduler.TestScheduler]. + * + * It is JavaScript friendly, it returns `Promise` which, when returned from a test method, + * causes the test to wait for completion. In all other targets [Completable.blockingAwait()][blockingAwait] is used. + * + * Please note the following factors: + * - The [mainScheduler][com.badoo.reaktive.scheduler.mainScheduler] is not available in + * Android unit tests and will crash if used; + * - Darwin (Apple) tests are executed on the Main thread and so using the + * [mainScheduler][com.badoo.reaktive.scheduler.mainScheduler] from this method will cause dead lock. + * + * To avoid the problems above use [overrideSchedulers][com.badoo.reaktive.scheduler.overrideSchedulers] + * to replace schedulers with [TestScheduler][com.badoo.reaktive.test.scheduler.TestScheduler] or + * with [TrampolineScheduler][com.badoo.reaktive.scheduler.TrampolineScheduler]. + * + * Usage example: + * ``` + * class MyLogic { + * fun div(a: Int, b: Int): Single = + * singleFromFunction { a / b } + * .subscribeOn(computationScheduler) + * } + * + * class MyLogicTest { + * @Test + * fun returns_2_WHEN_div_6_by_3() = + * MyLogic() + * .div(6, 3) + * .testAwait { assertEquals(2, it) } + * + * @Test + * fun throws_ArithmeticException_WHEN_div_by_0() = + * MyLogic() + * .div(6, 0) + * .testAwait(assertError = { assertTrue(it is ArithmeticException) }, assertSuccess = { fail("Did not throw") }) + * } + * ``` + * + * @receiver a [Single] for which the test should wait before completing + * @param assertError when provided, it will be called in case of [Single] error and + * the test will fail only when this callback throws an exception. + * This gives an opportunity to assert the error. + * @param assertSuccess when provided, it will be called in case of [Single] success. + * This gives an opportunity to assert the result. + */ +expect fun Single.testAwait(assertError: ((Throwable) -> Unit)? = null, assertSuccess: (T) -> Unit = {}) diff --git a/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt b/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt deleted file mode 100644 index fdcca0270..000000000 --- a/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/completable/TestAwaitTest.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.badoo.reaktive.test.completable - -import com.badoo.reaktive.completable.completableFromFunction -import com.badoo.reaktive.completable.completableOfEmpty -import com.badoo.reaktive.completable.completableOfError -import com.badoo.reaktive.completable.onErrorResumeNext -import com.badoo.reaktive.completable.subscribeOn -import com.badoo.reaktive.scheduler.computationScheduler -import kotlin.test.Test -import kotlin.test.assertSame - -class TestAwaitTest { - - @Test - fun awaits_success() = - completableOfEmpty() - .subscribeOn(computationScheduler) - .testAwait() - - @Test - fun awaits_error() { - val error = Exception() - - return completableOfError(error) - .subscribeOn(computationScheduler) - .onErrorResumeNext { - completableFromFunction { - assertSame(error, it) - } - } - .testAwait() - } -} diff --git a/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/single/TestAwaitTest.kt b/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/single/TestAwaitTest.kt new file mode 100644 index 000000000..0c1eb00f0 --- /dev/null +++ b/reaktive-testing/src/commonTest/kotlin/com/badoo/reaktive/test/single/TestAwaitTest.kt @@ -0,0 +1,28 @@ +package com.badoo.reaktive.test.single + +import com.badoo.reaktive.single.singleOf +import com.badoo.reaktive.single.singleOfError +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertSame + +class TestAwaitTest { + + @Test + fun succeeds_WHEN_upstream_succeeded_and_no_assertSuccess() = + singleOf(1) + .testAwait() + + @Test + fun succeeds_WHEN_upstream_succeeded_and_assertSuccess_did_not_throw() = + singleOf(1) + .testAwait(assertSuccess = { assertEquals(1, it) }) + + @Test + fun succeeds_WHEN_upstream_failed_and_assertError_did_not_throw() { + val error = Exception() + + return singleOfError(error) + .testAwait(assertError = { assertSame(error, it) }) + } +} diff --git a/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt b/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt deleted file mode 100644 index 86a3483cf..000000000 --- a/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.badoo.reaktive.test.completable - -import com.badoo.reaktive.completable.Completable -import com.badoo.reaktive.completable.asSingle -import com.badoo.reaktive.single.asPromise - -actual fun Completable.testAwait(): dynamic = - asSingle(Unit).asPromise() diff --git a/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt b/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt new file mode 100644 index 000000000..f7fb98e8e --- /dev/null +++ b/reaktive-testing/src/jsMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt @@ -0,0 +1,28 @@ +package com.badoo.reaktive.test.single + +import com.badoo.reaktive.single.Single +import com.badoo.reaktive.single.asPromise +import com.badoo.reaktive.single.doOnBeforeSuccess +import com.badoo.reaktive.single.map +import com.badoo.reaktive.single.onErrorReturn + +actual fun Single.testAwait(assertError: ((Throwable) -> Unit)?, assertSuccess: (T) -> Unit): dynamic = + if (assertError == null) { + doOnBeforeSuccess(assertSuccess) + .asPromise() + } else { + map { TestAwaitResult.Success(it) } + .onErrorReturn { TestAwaitResult.Error(it) } + .doOnBeforeSuccess { result -> + when (result) { + is TestAwaitResult.Success -> assertSuccess(result.value) + is TestAwaitResult.Error -> assertError(result.error) + } + } + .asPromise() + } + +private sealed class TestAwaitResult { + class Success(val value: T) : TestAwaitResult() + class Error(val error: Throwable) : TestAwaitResult() +} diff --git a/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt b/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt deleted file mode 100644 index c05e32a74..000000000 --- a/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/completable/TestAwait.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.badoo.reaktive.test.completable - -import com.badoo.reaktive.completable.Completable -import com.badoo.reaktive.completable.blockingAwait - -actual fun Completable.testAwait() { - blockingAwait() -} diff --git a/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt b/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt new file mode 100644 index 000000000..a7ac5e6f0 --- /dev/null +++ b/reaktive-testing/src/jvmNativeCommonMain/kotlin/com/badoo/reaktive/test/single/TestAwait.kt @@ -0,0 +1,20 @@ +package com.badoo.reaktive.test.single + +import com.badoo.reaktive.single.Single +import com.badoo.reaktive.single.blockingGet + +actual fun Single.testAwait(assertError: ((Throwable) -> Unit)?, assertSuccess: (T) -> Unit) { + if (assertError == null) { + assertSuccess(blockingGet()) + } else { + val result = + try { + blockingGet() + } catch (e: Throwable) { + assertError(e) + return + } + + assertSuccess(result) + } +}