In Scalatest when using matchers you have many ways to test for equality, but only one of those is type-safe - should ===()
So, if you have a function returning Int
, like
def f(i: Int): Int = i
then the only type-safe way to test it is to use should ===()
syntax, like
f(5) should ===(5)
The other matchers will also work
f(5) should be(5)
f(5) shouldBe 5
f(5) should equal(5)
f(5) shouldEqual 5
but if you change return type of your function (let's say to String
- def f(i:Int): String = i.toString
), then they will continue to compile, but fail at runtime.
Not a big deal one might say, and that's true. Sort of. I would prefer my code not even compile so that I know about the issue ASAP. That's one of the reasons we have type systems.
So should ===(5)
is the way to go. But to my personal taste it's somewhat less readable than for example shouldBe
.
First thing I don't like about it is the mix - one word (should
) and one symbolic operator(===
). The second sub-optimal thing is mandatory ()
around right side. As I mentioned above, shouldBe
solves both of those issues, but is not type-safe.
We do have a base class for all our tests (as suggested by scalatest guide), so we added the following code to get easy-to-read and type-safe way of equality check
class MyBaseSpec extends WordSpec with Matchers {
implicit class ShouldEqOps[A: Equality](left: A) {
def shouldEq(right: A) = left shouldEqual right
}
}
And now most of our equality checks are type-safe and read nicely
f(5) shouldEq 5