【问题标题】:Is there a specs matcher that will unbox Option and Either是否有一个规格匹配器可以将 Option 和 Either 拆箱
【发布时间】:2012-07-27 09:03:43
【问题描述】:

我创建了一个规范测试,以验证一些 JSON 解析。虽然测试效果非常好,但感觉相当嘈杂。

我想知道 Specifications 中是否有现有代码可以将 Option 和 Either 拆箱?

"twitter json to Scala class mapper" should {
    "parsing a tweet" in {
      TwitterJsonMapper.tweetP(tweetS) match {
        case Right(t: Tweet) => {
          implicit def unOption[T](t: Option[T]): T = t.get
          implicit def unEither[T](t: Either[T,Throwable]): T = t match {case Left(left) => left ;case Right(t) => throw t}
          "test id" in {
            true must_== (t.id.get == 228106060337135617l)
          }
          "test id_str" in {
            true must_== (t.id_str.get == "228106060337135617")
          }
          "test time" in {
            true must_== (t.created_at.getHours == 13 )
          }
        }
        case Left((pe: JsonParseException, reason: String)) => fail(reason + "\n" + pe)
      }
    }
  }

 //The Tweet is produced from JSON using Fasterxml's Jackson-Scala library. 
 //I want to use Option or Either monads over all child attributes - for the usual reasons.
case class Tweet(
  @BeanProperty contributors: Option[String],
  @BeanProperty coordinates: Option[String],

  @BeanProperty @JsonDeserialize (
      using = classOf[TwitterDateDeserializer]
  ) created_at: Either[Date,Throwable],
  @BeanProperty favorited: Boolean = false,
  //elided etc etc
  @BeanProperty id_str: Option[String]
}

【问题讨论】:

  • 是的,请参阅匹配器指南:etorreborre.github.com/specs2/guide/…
  • 啊,好的。我忘了说,我还在 Specs 1 上。只有这么多时间花在升级我的库上。该功能不在 Specs 1 中吗?
  • 很难获得可靠的 scala / maven / eclipse / specs - 工具链 - 启动并运行。我获得了使用 Eclipse 的规范,并冻结了我的依赖项的那部分。
  • 您在升级过程中遇到过什么问题吗?
  • 我是从 specs2 开始的,所以我无法对迁移发表评论。由于社区变化的步伐,我虔诚地升级了我的 Scala 项目。我发现 Gradle 优于 SBT/Maven,已经广泛使用。对于 specs1 匹配器,请参阅code.google.com/p/specs/wiki/MatchersGuide

标签: scala bdd specs


【解决方案1】:

我认为这没有必要。请记住,Option/Either 具有相等的值。只需匹配 Option/Either 而不是匹配它们包含的值。

      "Option should match other options" >> {
        Some(21) must be equalTo Some(21)
      }

      "Either should match Either" >> {
        Right("Some string") must be equalTo Right("Some string")
      }

我没有尝试编译这些,但它们应该可以工作。您可能需要添加一些显式类型(或使用类型不安全的must_==

      t.id must be equalTo Some(228106060337135617l)
      t.id_str must be equalTo Some("228106060337135617")
      t.created_at.left.map(_.getHours) must be equalTo Left(13)

【讨论】:

  • 试图减少混乱,有 34 个属性需要验证
  • 好吧,通常我不会包装我试图验证的每个属性。我这样做只是因为它在你的例子中。我更新以消除额外的规格混乱。
【解决方案2】:

OptionEither 确实有一些特定的匹配器:

t.id must beSome(228106060337135617l)
t.id_str must beSome("228106060337135617")
t.created_at.left.map(_.getHours) must beLeft(13)

【讨论】:

  • 顺便说一下,当你想测试一个布尔值时,你可以写(t.id.get == 228106060337135617l) must beTrue而不是写true must_== (t.id.get == 228106060337135617l)
  • 是的,这样更美观
  • 这些匹配器不是类型安全的。 Left(24) must beLeft("FUBAR")Some(42) must beSome("FUBAR") 都可以编译。他们只在运行时失败。从长远来看,额外的几句话将值得您浪费时间试图找出您的测试失败的原因。
  • 哇。唐纳!哦,好吧,这真的只是为了进行健全性检查,值得把它放在那里,看看社区是怎么做的。
猜你喜欢
  • 2021-05-31
  • 2019-06-06
  • 1970-01-01
  • 2013-06-21
  • 2018-06-23
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多