用 Scalatest 猫 `Eq` 的 `===`

cats `Eq`'s `===` with Scalatest

我正在阅读 Scala with Cats,在本书的第一章中,他们描述了 Eq 用法。

其中一个练习是关于编写该类型类的一个实例来验证两个 cats 的相等性。考虑一下:

型号

final case class Cat(name: String, age: Int, color: String)

类型类实例

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
  }

}

单元测试

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
  }

}

第一个测试工作正常,但第二个测试没有,因为 === 运算符是 Scalatest 运算符,而不是 Eq 运算符。

我探索了类型类是否有任何语法或隐含的语法,但我找不到任何相关信息。我在 this PR that there's a solution for this, based on Bill Venner's solution 中看到了,但这仅适用于猫自己的单元测试。

我一直在研究 EqSyntax 特性,但我不知道如何 覆盖 scalatest 自己的 === 实现。

有什么办法吗?或者这还没有实现?

谢谢

我不确定我是否正确理解了你的问题,但看起来你可以根据你引用的 PR 重新使用 Cats 为他们自己的测试实现的内容。只需将测试 class 定义更改为

class EqTest extends FlatSpec with Matchers with cats.tests.StrictCatsEquality  {

然后你可以编写测试,例如

optionCat1 === optionCat2 shouldBe false

optionCat1 should !== (optionCat2)

他们会使用您的 Eq[Cat] 定义(如果它被导入范围)。

基本上这个想法是 ScalaTest === 使用一些隐含的,例如 CanEqual。因此,如果您提供(导入)您的自定义隐式实现 - 您可以更改 === 内部的工作方式。