自定义喷雾拒绝处理程序在测试中无法正常工作

Custom spray rejection handler not working properly in tests

我正在使用 spray 构建一些 JSON HTTP 服务,但我在测试 RejectionHandler 时遇到了一些问题。如果我启动应用程序 运行 命令 sbt run 并发出请求,RejectionHandler 按预期处理 MalformedRequestContentRejection 但当 运行 甚至在路线封闭的情况下进行测试。另一方面,MethodRejection 工作正常。 JSON 验证是使用 require

完成的

下一个例子基于spray-templaterepository branch on_spray-can_1.3_scala-2.11 with a POST endpoint and the new tests. I've made a fork with the entire example 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"
      }
    }
  }
}

我错过了什么?

提前致谢!

您的 SomeReq class 正在 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"
}