2015-08-29 3 views
0

Я строю некоторые службы HTTP JSON, используя spray, и у меня возникают некоторые проблемы с тестированием RejectionHandler. Если я запустил приложение, выполнив команду sbt run и сделав запрос, RejectionHandler обработает MalformedRequestContentRejection, как и ожидалось, но я получаю IllegalArgumentException при запуске тестов даже при герметичности маршрута. С другой стороны, MethodRejection отлично работает. Проверка JSON выполняется с помощью requireПользовательский обработчик отбраковки отказов не работает должным образом в тестах

Следующий пример основан в spray-templaterepositoryon_spray-can_1.3_scala-2.11 ветви с конечной точкой POST и новые испытания. Я сделал вилку со всем, например here

Обратите внимание на использование case clase для десериализации JSONs, использование метода require для проверки и декларации неявной RejectionHandler.

package com.example 

import akka.actor.Actor 
import spray.routing._ 
import spray.http._ 
import StatusCodes._ 
import MediaTypes._ 
import spray.httpx.SprayJsonSupport._ 

class MyServiceActor extends Actor with MyService { 
    def actorRefFactory = context 
    def receive = runRoute(myRoute) 
} 

case class SomeReq(field: String) { 
    require(!field.isEmpty, "field can not be empty") 
} 
object SomeReq { 
    import spray.json.DefaultJsonProtocol._ 
    implicit val newUserReqFormat = jsonFormat1(SomeReq.apply) 
} 

trait MyService extends HttpService { 
    implicit val myRejectionHandler = RejectionHandler { 
    case MethodRejection(supported) :: _ => complete(MethodNotAllowed, supported.value) 
    case MalformedRequestContentRejection(message, cause) :: _ => complete(BadRequest, "requirement failed: field can not be empty") 
    } 
    val myRoute = 
    pathEndOrSingleSlash { 
     post { 
     entity(as[SomeReq]) { req => 
      { 
      complete(Created, req) 
      } 
     } 
     } 
    } 
} 

Это есть тест реализован с использованием spray-testkit. Последний ожидает BadRequest, но тест завершился неудачно с IllegarArgumentException.

package com.example 

import org.specs2.mutable.Specification 
import spray.testkit.Specs2RouteTest 
import spray.http._ 
import StatusCodes._ 
import spray.httpx.SprayJsonSupport._ 

class MyServiceSpec extends Specification with Specs2RouteTest with MyService { 
    def actorRefFactory = system 

    "MyService" should { 
    "leave GET requests to other paths unhandled" in { 
     Get("/kermit") ~> myRoute ~> check { 
     handled must beFalse 
     } 
    } 
    "return a MethodNotAllowed error for PUT requests to the root path" in { 
     Put() ~> sealRoute(myRoute) ~> check { 
     status should be(MethodNotAllowed) 
     responseAs[String] === "POST" 
     } 
    } 
    "return Created for POST requests to the root path" in { 
     Post("/", new SomeReq("text")) ~> myRoute ~> check { 
     status should be(Created) 
     responseAs[SomeReq] === new SomeReq("text") 
     } 
    } 
    /* Failed test. Throws IllegalArgumentException */ 
    "return BadRequest for POST requests to the root path without field" in { 
     Post("/", new SomeReq("")) ~> sealRoute(myRoute) ~> check { 
     status should be(BadRequest) 
     responseAs[String] === "requirement failed: field can not be empty" 
     } 
    } 
    } 
} 

У меня пропало что-то?

Заранее благодарен!

ответ

2

Ваш SomeReq класс быть охотно инстанцирован в Post("/", new SomeReq("")) запроса застройщиком и метод require вызывается как только class конкретизируется.

Чтобы обойти эту проблему попробуйте использовать следующие вместо:

import spray.json.DefaultJsonProtocol._ 
Post("/", JsObject("field" → JsString(""))) ~> sealRoute(myRoute) ~> check { 
    status should be(BadRequest) 
    responseAs[String] === "requirement failed: field can not be empty" 
} 
+0

Спасибо! Работает как шарм. – Quaiks

Смежные вопросы