应当抛出scalatest拦截vs a [Exception]

时间:2018-08-28 21:50:04

标签: scala scalatest

我正在测试某些Future失败的情况,并以两种不同的方式进行了尝试,一种有效:

intercept[NoSuchElementException] {
  Await.result(dao.findById("some_id"), Duration.Inf)
}

和没有:

a[NoSuchElementException] should be thrownBy dao.findById("some_id")

以前发生在我身上,我正试图弄清楚为什么。

很乐意得到一些帮助来理解这一点。

findById仅在失败时抛出NoSuchElementException

  def findById(id: String): Future[Person] = {
    collection.find(json(Vendor.PersonId -> id))
      .requireOne[Person] recover {
      case NoSuchResultException => throw new NoSuchElementException
    }
  }

2 个答案:

答案 0 :(得分:3)

您面临的问题是Future的处理不正确。

给出以下定义:

def findById(id: String): Future[Person] = {
  collection.find(json(Vendor.PersonId -> id))
    .requireOne[Person] recover {
     case NoSuchResultException => throw new NoSuchElementException
    }
}

recover会将NoSuchResultException映射到throw new NoSuchElementException,但始终包裹在Future内。

这意味着返回的对象将是失败的Future,并且该方法不会引发任何异常。

要处理这种情况,您可以例如在scalatest中将测试类与ScalaFutures特性一起混合。这样可以帮助您像

dao.findById("some_id").failed.futureValue should be a[NoSuchElementException]

答案 1 :(得分:2)

考虑这是否是实现:

def findById(id: String): Future[Person] = Future {
  Thread.sleep(1000)
  throw new NoSuchElementException()
}

调用findById本身不会引发异常。它立即返回了这个未来。异常会在返回的Future中引发,因此只有在您对结果进行Await或以其他方式访问将来的结果时才会出现该异常。