I'm using Play 2.2.2 and have been unsuccessfully trying to add tests to my file upload functionality. I know there are plenty of questions about this, I have checked many but either they don't work or the API is deprecated and doesn't work or it fails with some spurious error.
This is how a valid request looks like from the browser (using Firefox's WebDeveloper plugin):
-----------------------------479326525221683770414613115
Content-Disposition: form-data; name="files[]"; filename="upload_aum_sample.csv"
Content-Type: text/csv
AccountName,AuM,Name
IX_CH1,10,A
IX_CH2,20,B
IX_CH3,30,C
IX_CH4,40,D
IX_CH5,50,E
IX_CH6,60,F
IX_CH7,70,G
IX_CH8,80,H
-----------------------------479326525221683770414613115--
This is what I have tried so far without success:
Compiles with a warning i.e. that routeAndCall
is deprecated:
"upload file correctly" in new WithApplication {
val fileName = "upload_aum_sample.csv"
val file = getClass().getResource(fileName).getFile()
val data = MultipartFormData(Map(), List(FilePart("files[]", fileName, Some("text/csv"), file)), List(), List())
val result = routeAndCall(FakeRequest(POST, "/aum/upload/do", FakeHeaders(), data).withSession("username" -> "Test")).get
status(result) must equalTo(OK)
contentType(result) must beSome.which(_ == "application/json")
}
and results in the Exception:
[info] ! upload file correctly
[error] MatchError: <function1> (of class play.core.Router$Routes$$anon$4) (Helpers.scala:187)
[error] play.api.test.RouteInvokers$$anonfun$routeAndCall$1.apply(Helpers.scala:187)
[error] play.api.test.RouteInvokers$$anonfun$routeAndCall$1.apply(Helpers.scala:187)
[error] play.api.test.RouteInvokers$class.routeAndCall(Helpers.scala:187)
[error] AumUploadPageSpec.routeAndCall(AumUploadPageSpec.scala:30)
[error] play.api.test.RouteInvokers$class.routeAndCall(Helpers.scala:178)
[error] AumUploadPageSpec.routeAndCall(AumUploadPageSpec.scala:30)
[error] AumUploadPageSpec$$anonfun$12$$anon$3$delayedInit$body.apply(AumUploadPageSpec.scala:73)
[error] play.api.test.WithApplication$$anonfun$around$1.apply(Specs.scala:20)
[error] play.api.test.WithApplication$$anonfun$around$1.apply(Specs.scala:20)
[error] play.api.test.PlayRunners$class.running(Helpers.scala:45)
[error] play.api.test.Helpers$.running(Helpers.scala:364)
[error] play.api.test.WithApplication.around(Specs.scala:20)
[error] play.api.test.WithApplication.delayedInit(Specs.scala:17)
[error] AumUploadPageSpec$$anonfun$12$$anon$3.<init>(AumUploadPageSpec.scala:48)
[error] AumUploadPageSpec$$anonfun$12.apply(AumUploadPageSpec.scala:48)
[error] AumUploadPageSpec$$anonfun$12.apply(AumUploadPageSpec.scala:48)
Compiles fine no warnings
"upload file correctly" in new WithApplication {
val fileName = "upload_aum_sample.csv"
val file = getClass().getResource(fileName).getFile()
val data = MultipartFormData(Map(), List(FilePart("files[]", fileName, Some("text/csv"), file)), List(), List())
val result = controllers.Application.uploadDo("aum")(FakeRequest(POST, "/aum/upload/do", FakeHeaders(), data).withSession("username" -> "Test")).run
status(result) must equalTo(OK) // <<<<<<< test fails here
contentType(result) must beSome.which(_ == "application/json")
}
But the test fails due to the server responding 400 instead of 200 i.e. not OK
[info] x upload file correctly
[error] '400' is not equal to '200' (AumUploadPageSpec.scala:53)
UPDATE 1: If embed the file content rather than the file I still get the same errors i.e. Change
val file = getClass().getResource(fileName).getFile()
to
val file = scala.io.Source.fromFile(getClass().getResource(fileName).getFile()).map(_.toByte).toArray
UPDATE 2: These are the routing and server side code respectively:
# Generic controllers
POST /:context/upload/do controllers.Application.uploadDo(context: String)
//------------------------------------------------------------------------
/**
* Action that uploads a file for a given context
* @param context the input context
*/
def uploadDo(context: String) = Action(parse.multipartFormData) { implicit request ⇒
request.body.file("files[]").map { file ⇒
val filename = file.filename
val contentType = file.contentType
}
Ok(Json.parse(
"""{"files": [
{
"name": "picture1.jpg",
"size": 902604,
"error": "Filetype not allowed"
},
{
"name": "picture2.jpg",
"size": 841946,
"error": "Filetype not allowed"
}
]}"""))
}