Spray.io test response not matching actual output

349 views Asked by At

I'm trying to set up some tests for an API made by a coworker with spray.io, and I'm encountering some odd behavior. When a request results in an error for any reason, we want to return a JSON value along the lines of:

{"status":false,"message":"useful message here"}

This happens just fine in the actual browser. I have navigated to an unhandled route in the web browser, and I get the desired JSON value. So, I want to test this. Now, since I'm new to spray.io, I started off with the very simple test:

"leave GET requests to root path unhandled" in {
  Get() ~> myRoute ~> check {
    handled must beFalse
  }
}

This went fine, no problems. Since it's my first time playing with spray.io, I looked at some of the sample tests for testing false routes, and wrapped myRoute with sealRoute() so I could check the response without failing tests:

"leave GET requests to root path unhandled" in {
  Get() ~> sealRoute(myRoute) ~> check {
    handled must beTrue
  }
}

This also works fine. So, I decided to just make sure the text of the response was usable with this, before I went to the trouble of parsing JSON and verifying individual values:

"leave GET requests to root path unhandled" in {
  Get() ~> sealRoute(myRoute) ~> check {
    responseAs[String] contains "false"
  }
}

This is failing. To investigate, I threw a simple line of code in to log the actual value of responseAs[String] to a file, and I got this:

The requested resource could not be found.

Can anyone tell me what I'm doing wrong? I'm thinking that one of the following is occurring:

  • responseAs[String] is doing more than taking the exact response and giving it back to me, applying some type of filter along the way
  • The framework itself is not fully evaluating the query, but rather making a mockup object for the test framework to evaluate, and therefore not executing the desired 'turn errors to json' methods that my co-worker has implemented

I have tried searching google and stack overflow specifically for similar issues, but I'm either not putting in the right queries, or most other people are content to have the default error messages and aren't trying to test them beyond checking handled must beFalse.

Edit - This is the relevant part of the RejectionHandler:

case MissingQueryParamRejection(paramName) :: _=>
  respondWithMediaType(`application/json`) {
    complete(BadRequest, toJson(Map("status" -> false, "message" -> s"Missing parameter $paramName, request denied")))
  }
1

There are 1 answers

0
childofsoong On

Okay, so with insight from here and a coworker, the problem has been found:

Basically, the custom RejectionHandler was defined within our custom Actor object, and it wasn't coming into scope in the tests. To resolve this, the following steps were taken:

  • Moved the definition for the custom RejectionHandler into its own object in a separate file (as it had to do its own imports, it was causing a "encountered unrecoverable cycle resolving import" error)
  • Imported this new object into both the original file and the test spec.

(fun fact - http://spray.io/documentation/1.2.2/spray-routing/key-concepts/rejections/#rejectionhandler seems to demonstrate the RejectionHandler as a top-level object but you can't have top-level implicit vals in Scala, hence the need for an object)