【问题标题】:Test MultipartFormData in Play 2.0 FakeRequest在 Play 2.0 FakeRequest 中测试 MultipartFormData
【发布时间】:2012-06-09 01:29:11
【问题描述】:

我正在尝试为 Play 2 控制器创建功能测试,该控制器将多部分表单数据作为输入。 FakeRequest 中目前没有支持多部分表单 POST 的方法。还有什么其他方法可以测试这个控制器?

Map<String, Object> map = new HashMap<String, Object>();
map.put("param1", "test-1");
map.put("param2", "test-2");
map.put("file", file)
Result result = routeAndCall(fakeRequest(POST, "/register").withFormUrlEncodedBody(map));// NO SUCH METHOD

编辑: 这是我为测试多部分所做的解决方法。

    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost("http://localhost:3333/blobupload");

    FileBody imageFile = new FileBody(new File("test/resources/test-1.jpg"));
    StringBody guid1 = null;
    StringBody guid2 = null;
    try {
        guid1 = new StringBody("GUID-1");

    } catch (UnsupportedEncodingException e1) {
        e1.printStackTrace();
    }

    MultipartEntity reqEntity = new MultipartEntity();
    reqEntity.addPart("key1", imageFile);
    reqEntity.addPart("key2", guid1);

    httppost.setEntity(reqEntity);

    HttpResponse response;
    try {
        response = httpclient.execute(httppost);
        HttpEntity resEntity = response.getEntity();

        assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
    } catch (ClientProtocolException e) {
        e.printStackTrace();
} catch (IOException e) {
        e.printStackTrace();
}

【问题讨论】:

    标签: java playframework-2.0


    【解决方案1】:

    你应该使用 callAction 来使用 withFormUrlEncodedBody

    @Test
    public void testMyAction() {
        running(fakeApplication(), new Runnable() {
            public void run() {                
                Map<String,String> data = new HashMap<String, Object>();
                data.put("param1", "test-1");
                data.put("param2", "test-2");
                data.put("file", file);
    
                Result result = callAction(
                    controllers.whatever.action(),
                    fakeRequest().withFormUrlEncodedBody(data)
                )
                ...
             }
         }
    }
    

    我只对 Play Framework 2 使用 Scala api,但我认为您不能使用 withFormUrlEncodedBody 测试多部分表单。

    你可以在 Scala 中这样做:

    import play.api.libs.Files._
    import play.api.mvc.MultipartFormData._
    
    class MyTestSpec extends Specification {
    
        "mytest should bla bla bla" in {
            running(FakeApplication(aditionalConfiguration = inMemoryDatabase())) {
                val data = new MultipartFormData(Map(
                    ("param1" -> Seq("test-1")),
                    ("param2" -> Seq("test-2"))
                ), List(
                    FilePart("payload", "message", Some("Content-Type: multipart/form-data"), play.api.libs.Files.TemporaryFile(new java.io.File("/tmp/pepe.txt")))
        ), List(), List())
    
                val Some(result) = routeAndCall(FakeRequest(POST, "/route/action", FakeHeaders(), data))
                ...
            }
        }
    }
    

    我猜你可以把它翻译成Java,对不起,我不知道如何用Java编码。

    P.D:对不起,我的英语还在学习中

    【讨论】:

    • 为什么withFormUrlEncodeBody需要callAction? routeAndCall 也应该有效。 routeAndCall(fakeRequest(POST, "/route").withFormUrlEncodedBody(map));
    • Mutlipartformdata 可能适用于 scala 与您的方法。但是,对于 java,withFormUrlEncodedBody 不允许映射具有 Object 类型的值。
    • 我不知道为什么 Java 风格需要 callAction,但似乎你只能用 callAction 调用 fakeRequest().withFormUrlEncodeBody,反正我对 Java 语言不太了解,所以我可以完全错误。我认为您不需要使用 withFormUrlEncodedBody 来测试您的多部分,您应该只构建正确的 POST 请求。
    • 不工作?抱歉,我不知道用于 Play(或 Java 语言)的 Java API 我是 Python/Scala 开发人员
    • 您不能将 HashMap() 映射到 Map
    【解决方案2】:

    最简单的方法是使用 Scala,如下所示:

    val formData = Map(
      "param-1" -> Seq("value-1"),
      "param-2" -> Seq("value-2")
    )
    val result = routeAndCall(FakeRequest(POST, "/register").copy(body=formData))
    

    这是假设你的控制器方法是这样的:

    def register = Action(parse.tolerantFormUrlEncoded) { ... }
    

    如果您真的必须使用 Java,您将无法访问命名参数,因此必须完整调用上面的“复制”方法。还要小心导入 scala play.api.test.FakeRequest 对象,因为 Java FakeRequest 代理没有复制方法。

    【讨论】:

    • formData中可以允许文件吗?
    【解决方案3】:

    这是一个使用 Java 中的 callAction() 为请求创建多部分/表单数据内容的解决方案。它至少在 Play 2.2.3 中有效。我的内容类型是 application/zip。您可能想要更改此设置。

    @Test
    public void callImport() throws Exception {
        File file = new File("test/yourfile.zip");
        FilePart<TemporaryFile> part = new MultipartFormData.FilePart<>(
                "file", "test/yourfile.zip",
                Scala.Option("application/zip"), new TemporaryFile(file));
        List<FilePart<TemporaryFile>> fileParts = new ArrayList<>();
        fileParts.add(part);
        scala.collection.immutable.List<FilePart<TemporaryFile>> files = scala.collection.JavaConversions
                .asScalaBuffer(fileParts).toList();
        MultipartFormData<TemporaryFile> formData = new MultipartFormData<TemporaryFile>(
                null, files, null, null);
        AnyContent anyContent = new AnyContentAsMultipartFormData(formData);
    
        Result result = callAction(
                controllers.routes.ref.ImportExport.import(),
                fakeRequest().withAnyContent(anyContent,
                        "multipart/form-data", "POST"));
    
        // Your Tests
        assertThat(status(result)).isEqualTo(OK);
    }
    

    【讨论】:

      【解决方案4】:
      Map<String, Object> data = new HashMap<String, Object>();
      map.put("param1", "test-1");
      map.put("param2", "test-2");
      
        final Http.RequestBuilder request = Helpers.fakeRequest()
                      .method(POST)
                      .bodyForm(formData)
                      .uri("/register");
      
              final Result result = route(app, request);
      

      【讨论】:

        猜你喜欢
        • 2013-11-08
        • 1970-01-01
        • 2013-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多