在Play 2.0 FakeRequest中测试MultipartFormData

时间:2012-06-05 01:11:23

标签: java playframework-2.0

我正在尝试为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

编辑: 这是我测试multipart的解决方法。

    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();
}

4 个答案:

答案 0 :(得分:7)

您应该使用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)
            )
            ...
         }
     }
}

我只使用Scala api用于Play Framework 2,但我认为你不能使用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:对不起我的英语我还在学习

答案 1 :(得分: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代理没有复制方法。

答案 2 :(得分:2)

这是一个Java中的callAction()解决方案,用于为请求创建multipart / form-data内容。它至少在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);
}

答案 3 :(得分:0)

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);