I am currently in the process of writing some Specs2 tests for may Play Framework 2.2.x application which accepts MultipartFormData submissions as part of it\'s function.
<(I've answered in the other thread: PlayFramework Testing: Uploading File in Fake Request Errors)
In short, you need a Writeable[AnyContentAsMultipartFormData], which turns MultipartFormData[TemporaryFile]
into Array[Byte]
, and you can take it from here: http://tech.fongmun.com/post/125479939452/test-multipartformdata-in-play
In Play 2.5.x, it is easy to test file upload
val file = new java.io.File("the.file")
val part = FilePart[File](key = "thekey", filename = "the.file", contentType = None, ref = file)
val request = FakeRequest().withBody(
MultipartFormData[File](dataParts = Map.empty, files = Seq(part), badParts = Nil)
)
val response = controller.create().apply(request)
status(response) must beEqualTo(201)
Rather than testing in a FakeApplication
which is slow and (in my experience) can be error-prone when tests are running in parallel, I've been unit testing my Multipart form upload handlers like this:
Split out the Play wiring from your actual upload handling in your controller; e.g.:
def handleUpload = Action(parse.multipartFormData) { implicit request =>
doUpload(request)
}
def doUpload(request:Request[MultipartFormData[TemporaryFile]]) = {
...
}
(Where handleUpload is the method in your routes
file that handles the POST
)
Now you've got an endpoint that's easier to get at, you can mock out your service layer to respond appropriately to good/bad requests, and inject the mock service into your controller under test (I won't show that here, there are a million different ways to do that)
Now mock out a multipart request that will arrive at your doUpload
method:
val request= mock[Request[MultipartFormData[TemporaryFile]]]
val tempFile = TemporaryFile("do_upload","spec")
val fileName = "testFile.txt"
val part = FilePart("key: String", fileName, None, tempFile)
val files = Seq[FilePart[TemporaryFile]](part)
val multipartBody = MultipartFormData(Map[String, Seq[String]](), files, Seq[BadPart](), Seq[MissingFilePart]())
request.body returns multipartBody
And finally, you can call your doUpload
method and verify functionality:
val result = controller.doUpload(request)
status(result) must beEqualTo(201)
By testing like this, you can quickly and easily test all the error-handling paths in your Controller
(which is probably what you're trying to do after all) without the overhead of needing to start the entire application.