ExceptionHandler не работает с аэрозольным тест-китом?

Я пытаюсь использовать Spray ExceptionHandler, используя пример из этого руководства: http://spray.io/documentation/1.2.2/spray-routing/key-concepts/exception-handling/

class MyServiceActor extends Actor with MyService  {

  def actorRefFactory = context

  def receive = runRoute(handleExceptions(myExceptionHandler)(myRoute))

  implicit def myExceptionHandler(implicit log: LoggingContext) =
    ExceptionHandler {
      case e: ArithmeticException =>
        requestUri { uri =>
          complete(InternalServerError, "Bad numbers, bad result!!!")
        }
    }
}

Я намеренно бросаю ArithmeticException в маршруте вот так:

trait MyService extends HttpService {

  val myRoute =
    path("") {
      get {
        complete {
          throw new ArithmeticException("Oops, I failed!")
          "Hello World"
        }
      }
    }
}

Если я сделал запрос с curl, он возвращает сообщение об ошибке Bad numbers, bad result!!! правильно. Однако при тестировании с помощью Specs2 + spray testkit он никогда не возвращает правильное сообщение об ошибке, вместо этого он возвращает сообщение об ошибке по умолчанию 500 кодов There was an internal server error, Даже используя sealRoute не помогает

"Test" in {
  Get() ~> sealRoute(myRoute) ~> check {
    println(responseAs[String]) // Always print `There was an internal server error.`
    ok
  }
}

А на консоли я бы увидел трассировку ошибки:

[ERROR] [07/07/2016 00:31:24.661] [specs2.DefaultExecutionStrategy-1] [ActorSystem(com-example-MyServiceSpec)] Error during processing of request HttpRequest(GET,http://example.com/,List(),Empty,HTTP/1.1)
java.lang.ArithmeticException: Oops, I failed!
        at com.example.MyService$$anonfun$1.apply(MyService.scala:62)
        at com.example.MyService$$anonfun$1.apply(MyService.scala:61)
        at spray.routing.directives.RouteDirectives$$anonfun$complete$1$$anon$3.apply(RouteDirectives.scala:49)
        at spray.routing.directives.RouteDirectives$$anonfun$complete$1$$anon$3.apply(RouteDirectives.scala:48)
        at spray.routing.directives.BasicDirectives$$anonfun$mapRequestContext$1$$anonfun$apply$1.apply(BasicDirectives.scala:30)
        ...

Я положил команду println в myExceptionHandler и обнаружил, что myExceptionHandler никогда не будет выполнен.

Кто-нибудь знает, почему не работает и решение?

1 ответ

По-видимому sealRoute недостаточно, потому что обработчик исключений разрешается неявно, как описано здесь: http://spray.io/documentation/1.2.4/spray-testkit/

В твоем случае, MyServiceActor имеет обработчик исключений, но в тестовом примере вы используете MyService/myRoute напрямую, поэтому обработчик исключений не берется.

Эта страница документации была полезна: http://spray.io/documentation/1.2.4/spray-routing/key-concepts/exception-handling/

Решение состоит в том, чтобы привести неявное ExceptionHandler в область применения в тестовом примере. Итак, в этом примере:

"Test" in {
  implicit val testExceptionHandler = ExceptionHandler {
    case e: ArithmeticException =>
      requestUri { uri =>
        complete(InternalServerError, "Bad numbers, bad result!!!")
      }
  }
  Get() ~> sealRoute(myRoute) ~> check {
    println(responseAs[String])
    ok
  }
}

Это сработало, но, конечно, дублирование не супер элегантно. Может быть, вы можете получить доступ к обработчику исключений из MyServiceActor в вашем тесте и повторно использовать производственный код. Я просто положил testExceptionHandler в базовый класс, все тесты наследуются от.

Другие вопросы по тегам