5

I am writing test-cases for my play application controller, and I am having trouble getting the action result.

val jsonresult = UserController.importOPML()( 
   FakeRequest(POST, "/user/import-opml",FakeHeaders(),data)
   .withCookies(cookie) 
)

this would work only when the Action is specified parse.multipartFormData, if it is changed to parse.json

type mismatch; found : play.api.libs.iteratee.Iteratee[Array[Byte],play.api.mvc.SimpleResult] required: scala.concurrent.Future[play.api.mvc.SimpleResult]

I don't know why , so I changed to

val Some(jsonresult ) = route( request )

this time the compilation can pass, but my Authentication stub cannot pass anymore. what is causing that weird error ? and if work with route, why the cookie didn't work.

zinking
  • 5,018
  • 4
  • 43
  • 76
  • put result in future block – Govind Singh Apr 28 '14 at 04:28
  • Can you post more of your code, for example one simplified test case. Btw. you should be able to get your stuff working by calling `contentAsString(jsonresult)` or `contentAsJson(jsonresult)` (make sure you have `import play.api.test.Helpers._` to use those). – lpiepiora May 01 '14 at 22:44

2 Answers2

6

This problem arises because play.api.mvc.Action[A] contains these two apply methods:

// What you're hoping for
def apply(request: Request[A]): Future[Result]

// What actually gets called
def apply(rh: RequestHeader): Iteratee[Array[Byte], Result]

Request[A] extends RequestHeader, so the A in this case makes all the difference. If it doesn't match the action, you'll call the wrong method.

If your action is a Action[AnyContent], then you must pass a Request[AnyContent] - Request[AnyContentAsJson] will work, but FakeRequest[JsValue] won't, because only the former is a Request[AnyContent].

When you use ActionBuilder with a BodyParser[A], you create an Action[A]. As a result, you'll need a Request[A] to test, which means that the type of data in your question is critically important.

  • parse.json returns a BodyParser[JsValue], so data must be a JsValue
  • parse.multipartFormData returns a BodyParser[MultipartFormData[TemporaryFile]], so data must be multi-part form data.

(Note: It's been a while since you asked this question, so I'm answering it using Play 2.3, rather than the 2.2 that you were using when it was asked.)

tjdett
  • 1,685
  • 1
  • 17
  • 21
  • 1
    I worked around using some other method. your answer sounds reasonable. what I am complaining is the API, which is not consistent at all. – zinking Sep 02 '14 at 09:28
  • 1
    I'm getting similar problems for my secured actions, is there a similar solution? http://stackoverflow.com/questions/26303705/secured-trait-causing-spec2-unit-test-compilation-errors – Ricardo Gladwell Oct 10 '14 at 16:14
  • This was it in my case. Constructing the `FakeRequest` via the case class constructor instead of the companion object's `apply` function fixed the issue for me. – blad Jun 20 '18 at 00:30
1

tjdett's answer explains the issue in detail.

For a quick solution that may work in your instance simply run the iteratee result payload.

val jsonresult = UserController.importOPML()( 
   FakeRequest(POST, "/user/import-opml",FakeHeaders(),data)
   .withCookies(cookie) 
).run
flurdy
  • 3,332
  • 26
  • 30