Search code examples
scalascalatest

scalatest intercept vs a[Exception] should be thrownBy


I'm testing some Future that fails, and I tried it in two different ways, one that works:

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

and one that dosen't:

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

It happened to me before, and I'm trying to figure out why is that..?

Would love to get some help understanding this.

findById simply throws NoSuchElementException if it fails:

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

Solution

  • The problem you are facing is that the Future is not handle correctly.

    Given this definition:

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

    the recover will map a NoSuchResultException into a throw new NoSuchElementException, but it always wrapped inside the Future.

    This means that returned object will be a failed Future and the method won't throw any exception.

    To handle such case you could, for example, mix-in your test class with the ScalaFutures trait in scalatest. This helps you to handle the future like

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