加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

针对’应该包含’的最新自定义匹配器

发布时间:2020-12-16 18:34:26 所属栏目:安全 来源:网络整理
导读:这是我经常遇到的情况,但我还没有找到解决方案. 假设您有一个人员列表,您只想验证人名. 这有效: persons.map(_.name) should contain theSameElementsAs(List("A","B")) 相反,我宁愿写这个 val toName: Person = String = _.namepersons should contain the
这是我经常遇到的情况,但我还没有找到解决方案.

假设您有一个人员列表,您只想验证人名.
这有效:

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执行此操作的方法.

我试图使用Explicitly trait中的’after being’语法,但这是不可能的,因为它采用’Normalization’来定义’normalized’方法对参数和返回类型使用相同的类型.所以不可能将Person更改为String.
此外,我还没有成功实现’明确’类似特征,因为它不喜欢我返回的Equality [.]类型和/或它不知道原始列表类型是什么,所以使用’_.name’确实不编译.

欢迎任何建议.

解决方法

您可以通过决定和适度滥用平等特征来管理类似的事情.这是因为Equality trait的areEqual方法接受泛型类型的参数和Any类型的参数,因此您可以使用它来比较Person和String,并通过简单地获取Equality对象来确定您不需要与常态.

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的行为那样完美,但它有效.

您甚至可以通过隐式转换将其添加到after之后获取您建议的beingMapped语法:

implicit class AfterExtensions(aft: TheAfterWord) {
    def beingMapped[S,T](map: S => T): Equality[S] = MappingEquality(map)
    }
  }

我确实试过通过Uniformity trait来实现它,它有类似的方法涉及Any,但遇到了问题,因为规范化是错误的方法:我可以从你的例子创建Uniformity [String]对象,但不是Uniformity [人]一个. (原因是有一个规范化的方法返回用于构造Equality对象的泛型类型,这意味着为了将字符串与字符串进行比较,左侧输入必须是一个字符串.)这意味着唯一的写入方式与正常情况下的预期vs实际值相反:

"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
  }

绝对不是你通常想写这个的方式.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读