[play-2.1-scala] problem with tests - FakeRequest and json

3,704 views
Skip to first unread message

meloniasty

unread,
Nov 19, 2012, 6:15:14 PM11/19/12
to play-fr...@googlegroups.com
Hi,

I'm getting problems with testing controller's method where input parameters are in json, for example:

val json = Json.obj(
          "email" -> JsString("fa...@email.pl"),
          "password" -> JsString("fakepassword")
        )

val req = FakeRequest(
          method = "POST",
          uri = "/user/test",
          headers = FakeHeaders(
            Seq("Content-type"->Seq("application/json"))
          ),
          body =  json
        )

val result = route(req).get
println(contentAsString(result))
status(result) must equalTo(OK)

and response content is always Bad Request - Invalid JSON

my routing is
POST /user/test controllers.user.test

if i run play in server mode and test via any rest browser client it's work perfectly

maybe its bug in 2.1 or i'm doing sth wrong ?

best regards
dawid

James Roper

unread,
Nov 19, 2012, 7:07:23 PM11/19/12
to play-fr...@googlegroups.com
Looks like a bug to me, I just reproduced it.  By the way, here is an easier way to create the fake request (it doesn't fix the problem though):

val req = FakeRequest("POST", "/user/test").withJsonBody(json)

James Roper

unread,
Nov 19, 2012, 7:32:47 PM11/19/12
to play-fr...@googlegroups.com
I've got a better solution for you.

Assuming this is your controller:

package controllers
object User {
 
def create(username: String) = Action(parse.json) { req =>
   
// Do something
   
Ok(req.body)
 
}
}

And here is your route

POST   /user/:username    controllers.User.create(username)

Then you can:

val json = Json.obj(
         
"email" -> JsString("test@example.com"),

         
"password" -> JsString("fakepassword")
       
)


val req
= FakeRequest().copy(body = json)

val result
= controllers.User.create("test")(req)
println
(contentAsString(result))
status
(result) must equalTo(OK)

That way you don't need to worry about the method or URI.


On Tuesday, 20 November 2012 10:15:14 UTC+11, meloniasty wrote:

Pascal Voitot Dev

unread,
Nov 20, 2012, 2:36:59 AM11/20/12
to play-fr...@googlegroups.com
Just to remind people about the new JSON syntax.
You can now write directly:

val json = Json.obj(
   
"email" -> "test@example.com",
    "password" -> "fakepassword"
)





--
 
 

meloniasty

unread,
Nov 20, 2012, 3:48:41 AM11/20/12
to play-fr...@googlegroups.com
cool, thanks, i'll try this solution :)

meloniasty

unread,
Nov 20, 2012, 3:53:20 AM11/20/12
to play-fr...@googlegroups.com
yeah, i know, but i tested every possibilties :)

with JsString, pure String, withJsonBody, raw body, Parse.Json :) in my case nothing works,

i'll try James solution for now

meloniasty

unread,
Nov 20, 2012, 4:33:16 PM11/20/12
to play-fr...@googlegroups.com
i tried this, but i exactly don't understand what should i do with Iteratee (i'm not familiar with Iteratee)

when i used
User.controller.test()(req)
i get
play.api.libs.iteratee.Iteratee[Array[Byte],play.api.mvc.Result] and how to get Result ? :)

it's complicated for me

James Roper

unread,
Nov 21, 2012, 12:19:03 AM11/21/12
to play-fr...@googlegroups.com
This is because your body parser doesn't match the content that you are supplying, so it's invoking the apply(RequestHeader) method instead of apply(Request[A]).  In your controller, what parser are you using?  If none, then it's expecting Request[AnyContent], so you need to set the body to AnyContentAsJson(json).  FakeRequest.withJsonBody() will do this for you.  If you're using parse.json, then it's expecting Request[JsValue], so you need to the body as json directly.

meloniasty

unread,
Nov 21, 2012, 1:52:28 AM11/21/12
to play-fr...@googlegroups.com
it's working :) thanks

Alex Jarvis

unread,
Nov 21, 2012, 5:16:37 AM11/21/12
to play-fr...@googlegroups.com
I love finding comments like this, it's like the hidden documentation :)

Pascal Voitot Dev

unread,
Nov 21, 2012, 5:58:54 AM11/21/12
to play-fr...@googlegroups.com
I'm currently writing some docs about JSON but JSON enhancements in Play2.1 are quite huge so lots of doc to write ;)

Pascal


--
 
 

James Roper

unread,
Nov 27, 2012, 12:06:43 AM11/27/12
to play-fr...@googlegroups.com
There is a known bug in 2.1-rc1.  Hopefully we'll have it fixed before the 2.1 release.


On Saturday, 24 November 2012 01:30:37 UTC+11, Mushtaq Ahmed wrote:
val req = FakeRequest().copy(body = json)


This does not work for me in 2.1-RC1. The copy method is resolved to the one in RequestHeader and not to the one auto-generated by case class FakeRequest. What am I missing?

Mushtaq Ahmed

unread,
Nov 27, 2012, 8:47:54 AM11/27/12
to play-fr...@googlegroups.com
It seems case classes do not generate copy method if they already have/inherit one. So renaming the copy method in RequestHeader to something else should fix. Is there a ticket where we can discuss this?


--
 
 

adel alfar

unread,
Jan 11, 2013, 3:38:13 PM1/11/13
to play-fr...@googlegroups.com
Hi Pascal,

Can you please post an example of the corresponding Java way of doing your code snippet and Jame's above?  Thanks!

Pascal Voitot Dev

unread,
Jan 11, 2013, 4:16:14 PM1/11/13
to play-fr...@googlegroups.com
On Fri, Jan 11, 2013 at 9:38 PM, adel alfar <ad...@oax.com> wrote:
Hi Pascal,

Can you please post an example of the corresponding Java way of doing your code snippet and Jame's above?  Thanks!


You can't write the following in Java as this is a pure functional construction.
You can use direct JSON creation in Java.
Look here: http://www.playframework.org/documentation/2.0.4/JavaJsonRequests

regards
Pascal
 
--
 
 

adel alfar

unread,
Jan 11, 2013, 5:55:29 PM1/11/13
to play-fr...@googlegroups.com
Thanks Pascal!  I was hoping for the nicer Scala API in Java as well...Are there any plans to "enrich" the Java JSON API like close to the Scala one?

Pascal Voitot Dev

unread,
Jan 11, 2013, 5:59:01 PM1/11/13
to play-fr...@googlegroups.com
On Fri, Jan 11, 2013 at 11:55 PM, adel alfar <ad...@oax.com> wrote:
Thanks Pascal!  I was hoping for the nicer Scala API in Java as well...Are there any plans to "enrich" the Java JSON API like close to the Scala one?


Actually, Scala API is purely functional. This isn't possible to do the same in Java for the time being (maybe later when JDK8 will be available and it's not even sure because we use a few advanced functional patterns).
So right now, the best is to use Jackson which is really quick and efficient JSON parser...
 
--
 
 

adel alfar

unread,
Jan 14, 2013, 11:59:18 AM1/14/13
to play-fr...@googlegroups.com
Again:  Thanks Pascal....I guess Scala "Expert" learning is not a bad idea for the long run....
Message has been deleted

angeloh

unread,
Feb 25, 2013, 4:14:13 AM2/25/13
to play-fr...@googlegroups.com
I tried with 

 val req = FakeRequest().withJsonBody(json).withHeaders(CONTENT_TYPE -> "application/json").copy(method = POST)

 val result = await(controllers.ProfileApiV1.update(member1.getMemberIdString())(req).run)


But I still get this error:

bad request at: /, Invalid Json

I am using Play 2.1

Andrew Garbutt

unread,
Mar 19, 2013, 12:17:50 PM3/19/13
to play-fr...@googlegroups.com
+1 on this issue in Play 2.1.  Has anyone discovered any workarounds or do we have to just wait till 2.1.1 or 2.2.?  This makes testing the controllers very difficult independent of the routing layer. 

Thanks,
Andy

Mushtaq Ahmed

unread,
Mar 19, 2013, 12:51:12 PM3/19/13
to play-fr...@googlegroups.com
On Monday, February 25, 2013 1:14:13 AM UTC-8, angeloh wrote:

 val req = FakeRequest().withJsonBody(json).withHeaders(CONTENT_TYPE -> "application/json").copy(method = POST)


I am using  FakeRequest().withBody(json) and it works perfectly well. Have you tried that?

Anuj Pratap Singh

unread,
Apr 19, 2013, 2:51:37 AM4/19/13
to play-fr...@googlegroups.com
 Hi James Roper,
                         I have a problem to sending data from Unit Testing of Controller by FakeRequest to Controller which accept data as a Quersy String . Please Suggest me how i send data to controller with FakeRequest.
my problem is like below :
Test Code :
running(FakeApplication()) {
    
    val result1 = controllers.UController.getUserById(
    FakeRequest().withHeaders(("id", uCreated.get.toString))) // Here we need to replace withHeader (?)
     assert(status(result1) === 200)
     assert(contentType(result1) === Some("application/json"))
}

Controller Code :
def getUById: Action[play.api.mvc.AnyContent] = Action { implicit request =>
    try {
     
      val idRequest = request.queryString.get("id").getOrElse(Seq())
}

Thanks
Reply all
Reply to author
Forward
0 new messages