这是我经常遇到的情况,但我还没有找到解决方案。
假设您有一个人员列表,并且您只想验证人名。 这有效:
persons.map(_.name) should contain theSameElementsAs(List("A","B"))
相反,我宁愿写这个像
val toName: Person => String = _.name
persons should contain theSameElementsAs(List("A","B")) (after mapping toName)
因为你会这么说。
但有时候,您希望使用自定义匹配器,它不仅仅匹配对象的一个属性。如何使用
persons should contain(..)
语法,但不知何故能够使用自定义匹配器?
我可以使用Hamcrest匹配器使用JUnit或TestNG轻松解决这两种情况,但我还没有找到使用ScalaTest执行此操作的方法。
我试图在'之后使用'来自显式特征的语法,但这是不可能的,因为这需要'规范化'它定义了'标准化' method对参数和返回类型使用相同的类型。因此无法将Person更改为String。 此外,我还没有成功地实施一个明确的'喜欢trait因为它不喜欢我返回的Equality [。]类型和/或它不知道原始列表类型是什么,所以使用' _。name'不编译。
欢迎任何建议。
答案 0 :(得分:2)
您可以通过单词decided
管理类似内容并轻度滥用Equality
特征。这是因为Equality
特征的areEqual
方法采用了泛型类型的参数和Any
类型的参数,因此您可以使用它来比较Person
String
和decided by
仅使用Equality
对象,这意味着您不必使用Normality
。
import org.scalactic.Equality
import org.scalatest.{FreeSpec, Matchers}
final class Test extends FreeSpec with Matchers {
case class Person(name: String)
val people = List(Person("Alice"), Person("Eve"))
val namesBeingEqual = MappingEquality[Person, String](p => p.name)
"test should pass" in {
(people should contain theSameElementsAs List("Alice", "Eve"))(
decided by namesBeingEqual)
}
"test should fail" in {
(people should contain theSameElementsAs List("Alice", "Bob"))(
decided by namesBeingEqual)
}
case class MappingEquality[S, T](map: S => T) extends Equality[S] {
override def areEqual(s: S, b: Any): Boolean = b match {
case t: T => map(s) == t
case _ => false
}
}
}
我不确定我是否认为这是一个好主意,因为它并没有像人们期望任何名为Equality
的行为那样表现,但它确实有效。
您甚至可以通过隐式转换将beingMapped
语法添加到after
来获得您建议的 implicit class AfterExtensions(aft: TheAfterWord) {
def beingMapped[S, T](map: S => T): Equality[S] = MappingEquality(map)
}
}
语法:
after
我确实尝试通过Uniformity
特征使Any
使用Uniformity[String]
特征,该特征具有涉及Uniformity[Person]
的类似方法,但遇到了问题,因为规范化是错误的方法:我可以从您的示例中创建normalized
对象,但不是Equality
对象。 (原因是' sa "test should succeed" in {
val mappedToName = MappingUniformity[Person, String](person => person.name)
(List("Alice", "Eve") should contain theSameElementsAs people)(
after being mappedToName)
}
case class MappingUniformity[S, T](map: S => T) extends Uniformity[T] {
override def normalizedOrSame(b: Any): Any = b match {
case s: S => map(s)
case t: T => t
}
override def normalizedCanHandle(b: Any): Boolean =
b.isInstanceOf[S] || b.isInstanceOf[T]
override def normalized(s: T): T = s
}
方法返回用于构造{CUSTOM FIELD LABEL}: {CUSTOM FIELD VALUE}
对象的泛型类型,这意味着为了将字符串与字符串进行比较,左侧输入必须是string。)这意味着写它的唯一方法是使用与正常情况相反的预期vs实际值:
__()
绝对不是你通常想写的。