我正在使用本指南中的示例尝试使用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)
...
我在myExceptionHandler
中放了一个println命令,发现myExceptionHandler永远不会被执行。
任何人都知道它为什么不起作用和解决方案?
答案 0 :(得分:0)
显然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
放入基类中,所有测试都继承自。