Exception not getting handled in recover method

泄露秘密 提交于 2020-06-29 06:41:52

问题


This method throws exception

  @throws(classOf[QuestionNotFoundException])
  def getQuestionFromQuestionID(questionKey: PracticeQuestionKeys) = {
    logger.trace(s"getting question with keys ${questionKey}")
    val practiceQuestionFuture: Future[Option[PracticeQuestion]] = findOne(questionKey)
    for (questionOption <- practiceQuestionFuture) yield {
      questionOption.fold(throw QuestionNotFoundException())(question => {
        logger.trace("got question " + question)
        question
      })
    }
  }

I use it like follows

def function1 = {
...
val res = for{existingQuestion <- questionsRepository.getQuestionFromQuestionID(questionKey){..}
res.recover {
                     case exception => {
                       logger.trace(s"exception ${exception}")
                       Ok(Json.toJson(JsonResultError(messagesApi("error.answerAdditionFail")(langs.availables(0))+". "+exception.getMessage())))
                     }
...
}

I want to test that function1 handles the thrown exception. I have written the following test case

"function" should {
    "should return error if the question id is not correct" in {
      ...

      when(answerTestEnv.mockPracticeQuestionsRepository.getQuestionFromQuestionID(ArgumentMatchers.any[PracticeQuestionKeys])).thenThrow(
        QuestionNotFoundException()
      )




      val response:Accumulator[ByteString,Result] = controller.function1(request)
      //note that run is how accumulator gets the data and starts processing it. no parameter means no data
      val resultOfAccumulatorRun:Future[Result] = response.run(ByteString(body))
      val responseBody = contentAsJson(resultOfAccumulatorRun)(Timeout(Duration(5000,"millis")),TestEnvImplicits.mat)

      println(s"received response ${responseBody}")
      val result = (responseBody \ "result").get.as[String]

      val additionalInfo = (responseBody \ "additional-info").get.as[String]

      result mustBe "error"
      additionalInfo mustBe components.messagesApi("error.answerAdditionFail")(components.langs.availables(0))+". "+QuestionNotFoundException().msg


    }

}

But when I run my test case, the Exception gets thrown but it seems that res.recover doesn't handle it. I see this in the console.

Question not found
utilities.QuestionNotFoundException: Question not found
    at controllers.AnswerController.$anonfun$newAnswer$1(AnswerController.scala:428)

Why doestres.recover` doesn't handle it.


回答1:


the partial function passed to recover() gets invoked on a failed Future, but your Future isn't a failed Future, it is a Future that contains an exception as its 'successful' result type (actually it will be forced to be something more like Future[AnyRef], as it could be either an Exception or a PracticeQuestion).

You probably don't want to be using Option.fold() like that. Instead try:

practiceQuestionFuture.flatMap { qOpt =>
          qOpt.map(q => Future(q))
              .getOrElse(Future.failed(QuestionNotFoundException()))
}

(NB: I'm not near a compiler to try this out right now, so I may have made a syntactical mistake or two, but there should be enough there to get you going).



来源:https://stackoverflow.com/questions/62000287/exception-not-getting-handled-in-recover-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!