【问题标题】:Check for unexpected exceptions using ScalaTest + ScalaCheck使用 ScalaTest + ScalaCheck 检查意外异常
【发布时间】:2015-01-29 09:29:56
【问题描述】:

我正在尝试使用 ScalaTest 编写一个基本上声明“它不应该抛出异常,或者抛出可能的异常列表之一”的属性,它是 GeneratorDrivenPropertyChecks,它反过来使用 scalatest。问题是我无法将noException 与逻辑或结合起来,所以我能想到的最好的就是这个丑陋的测试:

it should "not throw unexpected exceptions" in {
  forAll { (s: String) =>
    try { parse(s) }
    catch { case e:Throwable => e shouldBe a [ParsingFailedException] }
    true shouldBe true // prevent compile error
}}

我希望看到的内容更像

it should "not throw unexpected exceptions" in {
  forAll { (s: String) => {
    (noException should Be thrownBy) or (a [ParsingFailedException] shouldBe thrownBy) { parse(s)  }
}}

【问题讨论】:

  • 这种差异是不确定的吗?因为否则我建议将您的测试分为两种情况:一种用于不应抛出异常的情况,另一种用于应抛出列表之一。通过这种方式,其他读者也更清楚地知道什么时候应该发生

标签: scala testing scalatest scalacheck property-based-testing


【解决方案1】:

由于我们想使用异常作为值而不是控制异常流,我们可以使用scala.util.Try 并对Try 的值进行断言。因此,我们可以调用Try(parse(s)),而不是调用parse(s)

不幸的是,因为现在已经包装了这些值,所以除了编写自定义匹配器之外,我想不出一种干净的方法来断言谓词。对于您的具体示例,自定义匹配器可能如下所示:

class FailAsMatcher[E <: Throwable](t: Class[E]) extends Matcher[Try[Any]] {
  def apply(theTry: Try[Any]) =
    MatchResult(
      theTry.isFailure && (theTry.failed.get.getClass == t),
      s"did not fail as a $t",
      s"did fail as a $t"
    )
}

由于Try 是协变的,我们可以将自定义匹配器的泛型类型定义为Try[Any]。匹配器仅匹配Failure[Any] 的实例,这些实例因提供的类型异常而失败。现在,我们可以将其称为:

it should "not throw unexpected exceptions" in {
  forAll { (s: String) =>
    Try(parse(s)) should ( be ('success) or failAs(classOf[ParsingFailedException]))
  }
}

def failAs[E <: Throwable](t: Class[E]) = new FailAsMatcher[E](t)

现在,如果发生非预期异常,错误可能如下所示:

TestFailedException was thrown during property evaluation.
  Message: Failure(java.lang.NullPointerException) was not success, and did not fail as a class ParsingFailedException

【讨论】:

  • 也许我们可以将其更改为仅采用通用参数,即Try(parse(s)) should ( be ('success) or failAs[ParsingFailedException]),但我不确定如何实现。
  • 谢谢你,没想过实现自定义匹配器:)
猜你喜欢
  • 1970-01-01
  • 2015-11-21
  • 2016-05-20
  • 2012-04-09
  • 2023-03-17
  • 2013-10-31
  • 1970-01-01
  • 2017-01-14
  • 2014-12-29
相关资源
最近更新 更多