我目前正在为Play Framework 2.2.x应用程序编写一些Specs2测试,该应用程序接受MultipartFormData提交作为其功能的一部分。
我已使用以下格式成功地使用text和JSON主体编写了其他测试:
"respond to POST JSON with description field present" in {
running(FakeApplication()) {
val response = route(FakeRequest(POST, "/submission.json").withJsonBody(toJson(Map("content" -> toJson("test-content"), "description" -> toJson("test-description"))))).get
status(response) must equalTo(OK)
contentType(response) must beSome.which(_ == "application/json")
contentAsString(response) must contain(""""description":"test-description"""")
contentAsString(response) must contain(""""content":"test-content"""")
}
}
但是,当我使用.withMultipartFormData方法时,我会收到以下错误:
Cannot write an instance of play.api.mvc.AnyContentAsMultipartFormData to HTTP response. Try to define a Writeable[play.api.mvc.AnyContentAsMultipartFormData]
val response = route(FakeRequest(PUT,"/submission.json/1/files").withMultipartFormDataBody(data)).get
^
我尝试调试的MultipartFormData测试的形式如下:
"respond to file PUT form with details not specififed" in {
running(FakeApplication()) {
val basePath:String = Play.application.path.getCanonicalPath();
val data:MultipartFormData[TemporaryFile] = MultipartFormData(Map[String,Seq[String]](),
List(
FilePart("file_upload","",Some("Content-Type: multipart/form-data"),TemporaryFile(new java.io.File(basePath + "/test-data/testUpload.jpg")))
),
List(),
List())
val response = route(FakeRequest(PUT,"/submission.json/1/files").withMultipartFormDataBody(data)).get
status(response) must equalTo(CREATED)
}
}
查看相关版本的FakeRequest类的Play Framework文档,我看不到太多帮助我追查问题:play.api.test.FakeRequest
就其他有关此事的文件而言,Play Framework网站和谷歌似乎相当缺乏。
我尝试了以下替代方法来尝试测试我的MultipartFormData代码:
但是,我对这些方法都没有任何成功。
答案 0 :(得分:7)
当测试并行运行时,我不是在FakeApplication
中进行测试,而且速度很慢(根据我的经验)可能容易出错,我已经单元测试我的Multipart表单像这样上传处理程序:
从控制器中的实际上传处理中拆分播放接线; e.g:
def handleUpload = Action(parse.multipartFormData) { implicit request =>
doUpload(request)
}
def doUpload(request:Request[MultipartFormData[TemporaryFile]]) = {
...
}
(其中handleUpload是routes
文件中处理POST
的方法)
现在您已经有了一个更容易获得的端点,您可以模拟您的服务层以适当地响应好/坏请求,并将模拟服务注入您的控制器在测试中(我不会在这里显示,有一百万种不同的方法)
现在模拟了一个多部分请求,它将以doUpload
方式到达:
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
最后,您可以调用doUpload
方法和验证功能:
val result = controller.doUpload(request)
status(result) must beEqualTo(201)
通过这样的测试,您可以快速轻松地测试Controller
中的所有错误处理路径(这可能是您最终想要做的事情),而无需启动整个过程的开销应用
答案 1 :(得分:2)
(我在另一个帖子中回答:PlayFramework Testing: Uploading File in Fake Request Errors)
简而言之,您需要一个可写的[AnyContentAsMultipartFormData],它将MultipartFormData[TemporaryFile]
变为Array[Byte]
,您可以从此处获取它:http://tech.fongmun.com/post/125479939452/test-multipartformdata-in-play
答案 2 :(得分:2)
在Play 2.5.x中,可以轻松测试文件上传
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)