13

我目前正在为可能的 Play Framework 2.2.x 应用程序编写一些 Specs2 测试,该应用程序接受 MultipartFormData 提交作为其功能的一部分。

我已经使用以下形式成功编写了其他带有文本和 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 代码:

但是,我也没有在这些方法中取得任何成功。

4

3 回答 3

8

在并行运行测试时,我一直在对我的 Multipart 表单上传处理程序进行单元测试,而不是在FakeApplication缓慢且(根据我的经验)可能容易出错的测试中进行测试,如下所示:

  1. 从控制器中的实际上传处理中分离出 Play 接线;例如:

    def handleUpload = Action(parse.multipartFormData) { implicit request =>
      doUpload(request)
    }
    
    def doUpload(request:Request[MultipartFormData[TemporaryFile]]) = {
      ...
    }
    

    (其中 handleUpload 是routes文件中处理 的方法POST

  2. 现在你有了一个更容易访问的端点,你可以模拟你的服务层以适当地响应好/坏请求,并将模拟服务注入你的被测控制器(我不会在这里展示,有一百万种不同的方法来做到这一点)

  3. 现在模拟一个将到达您的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 
    
  4. 最后,您可以调用您的doUpload方法并验证功能

    val result = controller.doUpload(request)
    status(result) must beEqualTo(201)
    

通过这样的测试,您可以快速轻松地测试您的所有错误处理路径Controller(这可能是您最终尝试做的事情),而无需启动整个应用程序的开销。

于 2013-10-29T23:09:46.010 回答
6

在 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)
于 2016-10-17T05:19:48.780 回答
2

(我已经在另一个线程中回答了:PlayFramework Testing: Uploading File in Fake Request Errors

简而言之,您需要一个 Writeable[AnyContentAsMultipartFormData],它变成MultipartFormData[TemporaryFile]Array[Byte]您可以从这里获取:http ://tech.fongmun.com/post/125479939452/test-multipartformdata-in-play

于 2015-07-31T02:47:17.640 回答