13

私は現在、機能の一部として MultipartFormData 送信を受け入れる Play Framework 2.2.x アプリケーションの Specs2 テストをいくつか書いている最中です。

次のフォームを使用して、テキストと 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 フレームワークのドキュメントを見ると、問題を追跡するのに役立つ情報があまりありません: play.api.test.FakeRequest

また、この問題に関する他のドキュメントに関しては、Play Framework の Web サイトと Google にはかなり欠けているようです。

MultipartFormData コードをテストするために、次の代替手段を試しました。

ただし、これらのアプローチのいずれでも成功していません。

4

3 に答える 3

8

FakeApplicationテストが並行して実行されているときに遅く、(私の経験では) エラーが発生しやすい でテストするのではなく、次のようにマルチパート フォーム アップロード ハンドラーを単体テストしてきました。

  1. コントローラーでの実際のアップロード処理からPlay 配線を分割します。例えば:

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

    (ここで、handleUpload は、routesを処理するファイル内のメソッドですPOST)

  2. これで、より簡単に到達できるエンドポイントが得られました。サービス層をモックアウトして、良い/悪いリクエストに適切に応答し、テスト中のコントローラーにモック サービスを挿入できます (ここでは示しません。それを行うための100万の異なる方法)

  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 に答える