【问题标题】:Concise way to assert a value matches a given pattern in ScalaTest断言值与ScalaTest中给定模式匹配的简洁方法
【发布时间】:2015-02-01 09:50:38
【问题描述】:

有没有一种很好的方法来检查 ScalaTest 中的模式匹配是否成功? scalatest-users邮件列表中给出了一个选项:

<value> match {
  case <pattern> =>
  case obj => fail("Did not match: " + obj)
}

但是,它不会组合(例如,如果我想断言列表中的 2 个元素恰好与使用 Inspectors API 的模式匹配)。我可以编写一个匹配器,采用部分函数文字并在它已定义的情况下成功(如果我也想在消息中获取模式,它必须是一个宏)。有更好的选择吗?

【问题讨论】:

    标签: scala scalatest


    【解决方案1】:

    我不是 100% 确定我理解你所问的问题,但一个可能的答案是使用 Inside 特质的 inside。给定:

    case class Address(street: String, city: String, state: String, zip: String)
    case class Name(first: String, middle: String, last: String)
    case class Record(name: Name, address: Address, age: Int)
    

    你可以写:

    inside (rec) { case Record(name, address, age) =>
      inside (name) { case Name(first, middle, last) =>
        first should be ("Sally")
        middle should be ("Ann")
        last should be ("Jones")
      }
      inside (address) { case Address(street, city, state, zip) =>
        street should startWith ("25")
        city should endWith ("Angeles")
        state should equal ("CA")
        zip should be ("12345")
      }
      age should be < 99
    }
    

    这适用于断言或匹配器。详情在这里:

    http://www.scalatest.org/user_guide/other_goodies#inside

    如果您使用匹配器并且只想断言某个值与特定模式匹配,则可以使用 matchPattern 语法:

    val name = Name("Jane", "Q", "Programmer")
    name should matchPattern { case Name("Jane", _, _) => }
    

    http://www.scalatest.org/user_guide/using_matchers#matchingAPattern

    您指出的 scalatest-users 帖子是 2011 年发布的。从那时起,我们就为这个用例添加了上述语法。

    比尔

    【讨论】:

      【解决方案2】:

      这可能不是你想要的,但你可以使用这样的习语来编写你的测试断言。

      import scala.util.{ Either, Left, Right }
      // Test class should extend org.scalatest.AppendedClues
      
      val result = value match {
        case ExpectedPattern => Right("test passed")
        case _ => Left("failure explained here") 
      })
      result shouldBe 'Right withClue(result.left.get)
      

      这种方法利用了 Scala match 表达式产生值这一事实。

      这是一个更简洁的版本,不需要特征 AppendedClues 或将匹配表达式的结果分配给 val

      (value match {
        case ExpectedPattern => Right("ok")
        case _ => Left("failure reason")
      }) shouldBe Right("ok")
      

      【讨论】:

      • 我实际上认为它比问题中的解决方案更糟糕:失败给出的信息不太有用。
      • 这很好。我已经改进了解决该问题的答案,但此解决方案可能无法满足您“简洁”的目标。
      猜你喜欢
      • 2016-05-14
      • 1970-01-01
      • 2011-05-12
      • 2021-04-13
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多