Reputation: 5262
I am relatively new to Scala Test, and so I consulted the documentation on how to test on Either
values.
I tried to replicate the instructions like that:
import org.scalatest.EitherValues
import org.scalatest.flatspec.AnyFlatSpec
class EitherTest extends AnyFlatSpec with EitherValues {
val either: Either[Exception, Int] = Right(42)
either.right.value should be > 1
}
This implementation does not do the trick, I get a syntax error. What did I do wrong?
Error:
Error:(9, 22) value should is not a member of Int
either.right.value should be > 1
Error:(9, 29) not found: value be
either.right.value should be > 1
Upvotes: 10
Views: 6593
Reputation: 21123
The code isn't compiling since the class is missing the Matchers
trait, which is necessary in order to use the "should" DSL API. Adding with Matchers
to the class declaration fixes the compilation error.
import org.scalatest.EitherValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class EitherTest extends AnyFlatSpec with EitherValues with Matchers {
val either: Either[Exception, Int] = Right(42)
either.right.value should be > 1
}
Additionally, since right
is deprecated since Scala 2.13.0, the value
method can be directly called on the Either
to avoid the deprecated member usage and associated warning, instead of using either.right.value
.
either.value should be > 1
Upvotes: 1
Reputation: 48410
There was an open pull request Add EitherValuable #1712 which aimed to address the fact that in Scala 2.13 the RightProjection
is deprecated:
at present
.right
is deprecated (and I believe it will stay that way) but.left
isn't, as per scala/scala#8012
However, this pull request was closed without accepting it, so it will not become part of Scala. Per the author's closing comments:
I lost interest in this
If this pull request had been accepted, the new syntax of EitherValues
in future ScalaTest versions might have become rightValue
and leftValue
like so
either.rightValue should be > 1
Upvotes: 7
Reputation: 2166
Did you consider the inside trait? That way you can test for the value inside your Either using pattern matching. For example:
import org.scalatest.Inside.inside
...
val result = FooBarInputValidator(value)
inside(result) { case Left(validationError) =>
validationError.message shouldBe "Invalid input"
validationError.parameter shouldBe "FooBar"
}
Upvotes: 2
Reputation: 1570
Testing Either by matching with pattern can be more readable.
ScalaTest's Inside
trait allows you to make assertions after a pattern match.
import org.scalatest.Inside
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class EitherTest extends AnyFlatSpec with Inside with Matchers {
val either: Either[Exception, Int] = Right(42)
either should matchPattern { case Right(42) => }
inside(either) { case Right(n) =>
n should be > 1
}
val either2: Either[Exception, Int] = Left(new Exception("Bad argument"))
inside(either2) { case Left(e) =>
e.getMessage should startWith ("Bad")
}
}
Upvotes: 9
Reputation: 14803
Here is how I would do it.
Check first if it is right and then compare the value:
either.isRight shouldBe true
either.getOrElse(0) shouldBe 42
Another way is to fail in case it is not right:
either.getOrElse(fail("either was not Right!")) shouldBe 42
I also would wrap your test, for example as WordSpec:
"My Either" should {
"be Right" in {
either.getOrElse(fail("either was not Right!")) shouldBe 42
}
}
This hints you where the problem is. Otherwise, if it fails, all you get is a nasty error stack.
And here the whole example:
class EitherTest
extends WordSpec
with Matchers
with EitherValues {
// val either: Either[Exception, Int] = Right(42)
val either: Either[Exception, Int] = Left(new IllegalArgumentException)
"My Either" should {
"be Right" in {
either.getOrElse(fail("either was not Right!")) shouldBe 42
}
}
}
Upvotes: 5