Как проверить 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()