用 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
。因此,如果您提供(导入)您的自定义隐式实现 - 您可以更改 ===
内部的工作方式。
我正在阅读 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
。因此,如果您提供(导入)您的自定义隐式实现 - 您可以更改 ===
内部的工作方式。