Как проверить Either от Arrow в функциональном стиле

Я хотел бы проверить полученный результат с помощью Either. Давайте предположим, что у меня есть простой пример без

@Test
fun `test arithmetic`() {
    val simpleResult = 2 + 2
    Assertions.assertEquals(4, simpleResult)
}

И теперь я завернул результат:

@Test
fun `test arithmetic with either`() {
    val result : Either<Nothing, Int> = (2 + 2).right()
    Assertions.assertTrue(result.isRight())
    result.map { Assertions.assertEquals(4, it) }
}

Я предполагаю, что это выглядит немного некрасиво, потому что последние утверждения не будут выполнены, если мы получили Either.Left вместо Either.Right Как правильно проверить результат в функциональном стиле?

4 ответа

Решение

котлинтест обеспечивает kotlintest-assertions-arrow модуль, который можно использовать для проверки типов стрелок.

Это в основном предоставляет сопоставления для любого или другого типа данных. Посмотрите на это.

@Test
fun `test arithmetic with either`() {
    val result : Either<Nothing, Int> = (2 + 2).right()
    result.shouldBeRight(4)
}

Реализации Either классы данных с обеих сторон, так что вы можете сделать что-то вроде:

check(result == 4.right())

Или может использовать нечто подобное с любой другой библиотекой утверждений, которая использует equals отстаивать равенство.

Для тех, кто использует библиотеку Google Truth , вы можете создать следующие расширения:

      import com.google.common.truth.Subject
import arrow.core.Either

fun Subject.isRight(){
    return this.isInstanceOf(Either.Right::class.java)
}
 
fun Subject.isLeft(){
    return this.isInstanceOf(Either.Left::class.java)
}

Затем используйте его в своих тестах:

      import com.google.common.truth.Truth.assertThat
import arrow.core.Either
 
@Test
fun `assert right`(){
    val result: Either<String, Unit> = getResult()
    assertThat(result).isRight()
}
 
@Test
fun `assert left`(){
    val result: Either<String, Unit> = getResult()
    assertThat(result).isLeft()
}

или если вы хотите проверить определенные значения вLeftилиRight:

      import com.google.common.truth.Truth.assertThat
import arrow.core.right
import arrow.core.left
import arrow.core.Either
 
@Test
fun `assert right`(){
    val result: Either<String, String> = Either.Right("test-string")
    assertThat(result).isEqualTo("test-string".right())
}
 
@Test
fun `assert left`(){
    val result: Either<String, String> = Either.Left("test-string")
    assertThat(result).isEqualTo("test-string".left())
}
 

Вы можете создавать функции расширения:

      fun <L, R> Either<L, R>.assertIsLeft(): L {
    return when (this) {
        is Either.Left -> value
        is Either.Right -> throw AssertionError("Expected Either.Left, but found Either.Right with value $value")
    }
}

fun <L, R> Either<L, R>.assertIsRight(): R {
    return when (this) {
        is Either.Right -> value
        is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value $value")
    }
}

fun <T: Any> T.assertEqualsTo(expected: T): Boolean {
    return this == expected
}

С ними тесты могут выглядеть так:

      val resultRight : Either<Nothing, Int> = (2 + 2).right()
resultRight
    .assertIsRight()
    .assertEqualsTo(4)

val resultLeft: Either<RuntimeException, Nothing> = RuntimeException("Some exception cause").left()
resultLeft
    .assertIsLeft()
Другие вопросы по тегам