Reputation: 1358
I was reading Scala with Cats and in the first chapter of the book, they describe Eq
usage.
One of the exercises is about writing an instance of that typeclass for validating the equality of two cats. Consider this:
Model
final case class Cat(name: String, age: Int, color: String)
Typeclass instance
import cats.Eq
import cats.syntax.eq._
import cats.instances.string._
import cats.instances.int._
import co.alejandrome.typeclass.model.Cat
object CatsEqInstances {
implicit val catsEq: Eq[Cat] = Eq.instance[Cat] {
(cata, catb) =>
cata.color === catb.color && cata.age === catb.age && cata.name === catb.name
}
}
Unit tests
import co.alejandrome.typeclass.model.Cat
import org.scalatest.{FlatSpec, Matchers}
import cats.instances.option._
class EqTest extends FlatSpec with Matchers{
import CatsEqInstances._
"Eq" should "compare two cats" in {
val cat1 = Cat("Garfield", 38, "orange and black")
val cat2 = Cat("Heathcliff", 33, "orange and black")
catsEq.eqv(cat1, cat2) shouldBe false
val cat3 = Cat("Garfield", 38, "orange and black")
catsEq.eqv(cat1, cat3) shouldBe true
}
it should "compare two Optional cats" in {
val cat1 = Cat("Garfield", 38, "orange and black")
//val cat2 = Cat("Heathcliff", 33, "orange and black")
val optionCat1 = Option(cat1)
val optionCat2 = Option.empty[Cat]
optionCat1 === optionCat2
}
}
The first test works fine, but the second one doesn't because ===
operator is the Scalatest one, not the Eq
one.
I explored if the typeclass has any syntax or implicit for this but I cannot find anything about it. I saw in this PR that there's a solution for this, based on Bill Venner's solution, but this is only for cats own unit tests.
I was poking with EqSyntax
trait but I can't figure it out how to override scalatest own implementation of ===
.
Is there any way to do this? Or is this not implemented yet?
Thanks
Upvotes: 2
Views: 1426
Reputation: 23788
I'm not sure if I understand your problem correctly, but it looks like you can re-use what Cats implemented for their own tests basing on the PR you referenced. Just change your test class definition to
class EqTest extends FlatSpec with Matchers with cats.tests.StrictCatsEquality {
and then you can write tests such as
optionCat1 === optionCat2 shouldBe false
or
optionCat1 should !== (optionCat2)
and they will you use your Eq[Cat]
definition (if it is imported into the scope).
Essentially the idea is that ScalaTest ===
uses some implicit such as CanEqual
. So if you provide (import) your custom implicit implementation - you can change how ===
works inside.
Upvotes: 3