parent
a40dcdf688
commit
bd7e1244b3
@ -91,6 +91,7 @@ kotlin {
|
||||
dependencies {
|
||||
implementation(kotlin("test-common"))
|
||||
implementation(kotlin("test-annotations-common"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.7")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
package com.github.michaelbull.result.coroutines
|
||||
|
||||
import com.github.michaelbull.result.BindException
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.ResultBinding
|
||||
import com.github.michaelbull.result.ResultBindingImpl
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Suspending variant of [binding][com.github.michaelbull.result.binding].
|
||||
*/
|
||||
suspend inline fun <V, E> binding(crossinline block: suspend ResultBinding<E>.() -> V): Result<V, E> {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
val receiver = ResultBindingImpl<E>()
|
||||
|
||||
return try {
|
||||
with(receiver) { Ok(block()) }
|
||||
} catch (ex: BindException) {
|
||||
receiver.error
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
/**
|
||||
* Workaround to use suspending functions in unit tests for multiplatform/native projects.
|
||||
* Solution was found here: https://github.com/Kotlin/kotlinx.coroutines/issues/885#issuecomment-446586161
|
||||
*/
|
||||
expect fun runBlockingTest(block: suspend (scope : CoroutineScope) -> Unit)
|
@ -0,0 +1,135 @@
|
||||
package com.github.michaelbull.result.coroutines
|
||||
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.runBlockingTest
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class SuspendableBindingTest {
|
||||
|
||||
private object BindingError
|
||||
|
||||
@Test
|
||||
fun returnsOkIfAllBindsSuccessful() {
|
||||
suspend fun provideX(): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Ok(1)
|
||||
}
|
||||
|
||||
suspend fun provideY(): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Ok(2)
|
||||
}
|
||||
|
||||
runBlockingTest {
|
||||
val result = binding<Int, BindingError> {
|
||||
val x = provideX().bind()
|
||||
val y = provideY().bind()
|
||||
x + y
|
||||
}
|
||||
|
||||
assertTrue(result is Ok)
|
||||
assertEquals(
|
||||
expected = 3,
|
||||
actual = result.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun returnsOkIfAllBindsOfDifferentTypeAreSuccessful() {
|
||||
suspend fun provideX(): Result<String, BindingError> {
|
||||
delay(1)
|
||||
return Ok("1")
|
||||
}
|
||||
|
||||
suspend fun provideY(x: Int): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Ok(x + 2)
|
||||
}
|
||||
|
||||
runBlockingTest {
|
||||
val result = binding<Int, BindingError> {
|
||||
val x = provideX().bind()
|
||||
val y = provideY(x.toInt()).bind()
|
||||
y
|
||||
}
|
||||
|
||||
assertTrue(result is Ok)
|
||||
assertEquals(
|
||||
expected = 3,
|
||||
actual = result.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun returnsFirstErrIfBindingFailed() {
|
||||
suspend fun provideX(): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Ok(1)
|
||||
}
|
||||
|
||||
suspend fun provideY(): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Err(BindingError)
|
||||
}
|
||||
|
||||
suspend fun provideZ(): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Ok(2)
|
||||
}
|
||||
|
||||
runBlockingTest {
|
||||
val result = binding<Int, BindingError> {
|
||||
val x = provideX().bind()
|
||||
val y = provideY().bind()
|
||||
val z = provideZ().bind()
|
||||
x + y + z
|
||||
}
|
||||
|
||||
assertTrue(result is Err)
|
||||
assertEquals(
|
||||
expected = BindingError,
|
||||
actual = result.error
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun returnsFirstErrIfBindingsOfDifferentTypesFailed() {
|
||||
suspend fun provideX(): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Ok(1)
|
||||
}
|
||||
|
||||
suspend fun provideY(): Result<String, BindingError> {
|
||||
delay(1)
|
||||
return Err(BindingError)
|
||||
}
|
||||
|
||||
suspend fun provideZ(): Result<Int, BindingError> {
|
||||
delay(1)
|
||||
return Ok(2)
|
||||
}
|
||||
|
||||
runBlockingTest {
|
||||
val result = binding<Int, BindingError> {
|
||||
val x = provideX().bind()
|
||||
val y = provideY().bind()
|
||||
val z = provideZ().bind()
|
||||
x + y.toInt() + z
|
||||
}
|
||||
|
||||
assertTrue(result is Err)
|
||||
assertEquals(
|
||||
expected = BindingError,
|
||||
actual = result.error
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
actual fun runBlockingTest(block: suspend (scope : CoroutineScope) -> Unit) = runBlocking { block(this) }
|
Loading…
Reference in New Issue
Block a user