6

If I have an endpoint that unmarshalls json like this:

(path("signup")& post) {
    entity(as[Credentials]) { credentials =>
    …

How can I test that with a Spray test spec:

"The Authentication service" should {

"create a new account if none exists" in {
   Post("/api/authentication/signup", """{"email":"foo", "password":"foo:" }""") ~> authenticationRoute ~> check {
    handled === true
  }
}
}

That obviously doesn't work for several reasons. What would be the correct way?

iwein
  • 25,788
  • 10
  • 70
  • 111

1 Answers1

12

The trick is to set the correct Content-Type:

Post("/api/authentication/signup", 
    HttpBody(MediaTypes.`application/json`, 
          """{"email":"foo", "password":"foo" }""")
)

But it gets even simpler. If you have a spray-json dependency, then all you need to do is import:

import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._

the first import contains (un)marshaller which would convert your string into json request and you do not need to wrap it into HttpEntity with explicit media type.

the second import contains all Json readers/writers format for basic types. Now you can write just: Post("/api/authentication/signup", """{"email":"foo", "password":"foo:" }"""). But it's even cooler if you have some case class for this. For ex. you can define a case class Credentials, provide jsonFormat for this and use it in tests/project:

case class Creds(email: String, password: String)
object Creds extends DefaultJsonProtocol {
  implicit val credsJson = jsonFormat2(Creds.apply)
}

now in test:

Post("/api/authentication/signup", Creds("foo", "pass"))

spray automatically marshall it into Json request as application/json

iwein
  • 25,788
  • 10
  • 70
  • 111
4lex1v
  • 21,367
  • 6
  • 52
  • 86
  • 8
    I believe this no longer works with the latest version. Instead, do this: ```Post("/api/authentication/signup", HttpEntity(MediaTypes.`application/json`, """{"email":"foo", "password":"foo" }""")))``` – Grega Kešpret Jun 03 '14 at 23:26
  • 1
    @GregaKešpret it perfectly works with any version. Currently on spray 1.3.1 with akka 2.3.3 – 4lex1v Jun 04 '14 at 04:53
  • 1
    @AlexIv Where is the object HttpBody located? – Grega Kešpret Jun 04 '14 at 09:32
  • @GregaKešpret when you import SprayJsonSupport into the scope it brings an implicit marshaller for objects for which you've defined JsonFormat or RootJsonFormat. The job of this marshaller is to convert your object into HttpEntity. – 4lex1v Jun 04 '14 at 10:21