【问题标题】:Unit testing file upload in a controller with Java Play Framework 2.3.x使用 Java Play Framework 2.3.x 在控制器中上传单元测试文件
【发布时间】:2015-09-25 22:30:12
【问题描述】:

在一天的大部分时间工作之后,我觉得我已经非常接近于如何测试一个接受来自 JUnit 的文件上传的控制器方法的解决方案了。我的juint测试代码如下:

Map<String, String> postData = makePostMap(uploadForm);
File file = new File("test/resources/shared/uploads/blank.csv");
TemporaryFile temporaryFile = new TemporaryFile(file);

MultipartFormData.FilePart filePath = new MultipartFormData.FilePart(
        "file",
        "file.csv",
        new scala.Some<>("text/csv"),
        temporaryFile);

List<MultipartFormData.FilePart> fileParts = Lists.newArrayList(filePath);
scala.collection.immutable.Seq files = JavaConversions.asScalaBuffer(fileParts).toList();

Map<String, scala.collection.immutable.Seq<String>> postData2 = new HashMap<>();
for (String s : postData.keySet()) {
    postData2.put(s, JavaConversions.asScalaBuffer(Lists.newArrayList(postData.get(s))).toList());
}
scala.collection.immutable.Map<String, scala.collection.immutable.Seq<String>> scalaMap =
        JavaConversions.mapAsScalaMap(postData2).toMap(Predef.<Tuple2<String, scala.collection.immutable.Seq<String>>>conforms());

MultipartFormData formData = new MultipartFormData(scalaMap, files, null, null);
AnyContentAsMultipartFormData body = new AnyContentAsMultipartFormData(formData);

// run
login(employee);
String url = routes.ManageContacts.uploadCsv().url();
FakeRequest fakeRequest = new FakeRequest(POST, url).withBody(body);
fakeRequest = getAuthenticatedRequest(fakeRequest, employee);

result = route(fakeRequest);

assertThat(status(result)).isEqualTo(OK)

但是,当 FakeRequest 被路由到时,我得到一个异常(如下)。

[error] Test controllers.ManageContactsTest.testUploadCsv failed: scala.MatchError: AnyContentAsMultipartFormData(MultipartFormData(Map(clearExisting -> List(false), survey -> List(11), bosMode -> List(false)),List(FilePart(file,file.csv,Some(text/csv),TemporaryFile(test/resources/shared/uploads/blank.csv))),null,null)) (of class play.api.mvc.AnyContentAsMultipartFormData), took 0.255 sec
[error]     at play.api.test.RouteInvokers$class.jRoute(Helpers.scala:255)
[error]     at play.api.test.Helpers$.jRoute(Helpers.scala:403)
[error]     at play.api.test.Helpers.jRoute(Helpers.scala)
[error]     at play.test.Helpers.route(Helpers.java:445)
[error]     at play.test.Helpers.route(Helpers.java:437)
[error]     at play.test.Helpers.route(Helpers.java:433)
[error]     at controllers.ManageContactsTest.testUploadCsv(ManageContactsTest.java:121)
[error]     ...

深入堆栈跟踪,我在文件中找到以下 scala match 语句: /Users/jcreason/bin/playframework-2.3.8/framework/src/play-test/src/main/scala/play/api/test/Helpers.scala:253

  def jRoute[T](app: Application, r: FakeRequest[T]): Option[Future[Result]] = {
    (r.body: @unchecked) match {
      case body: AnyContentAsFormUrlEncoded => route(app, r, body)
      case body: AnyContentAsJson => route(app, r, body)
      case body: AnyContentAsXml => route(app, r, body)
      case body: AnyContentAsText => route(app, r, body)
      case body: AnyContentAsRaw => route(app, r, body)
      case body: AnyContentAsEmpty.type => route(app, r, body)
      //case _ => MatchError is thrown
    }
  }

由于我通过AnyContentAsMultipartFormData,它会抛出这个异常,因为它没有被匹配处理。有谁知道如何解决这个问题?或者可以为我指出一个不同的解决方案的方向(除了像硒一样的明显答案)?

作为参考,我从以下代码中提取了一些代码:

http://www.erol.si/2014/02/how-to-test-file-uploads-in-play-framework-java/

【问题讨论】:

  • 大家好,我是这篇文章的作者。我用 Play 2.2 对此进行了测试,但似乎没有什么改变。我会用更新的版本测试它,但同时你可以在 scala github.com/playframework/playframework/blob/… 中查看示例
  • 当您使用 Java 时,看看这个可能会有所帮助:github.com/playframework/playframework/blob/…
  • 感谢@FrEaKmAn 的回复,我会在空闲时尝试检查 Scala 版本,谢谢。
  • @Anton,不幸的是,该示例是从接收者(控制器)的角度来看的,我试图从客户端或文件上传用户的角度进行自动化。
  • @jcreason 你找到解决方案了吗?我也面临同样的问题。

标签: java scala junit playframework playframework-2.3


【解决方案1】:

这段代码可能有用:

import static play.test.Helpers.*;
import static org.junit.Assert.*;
import java.util.*;
import org.junit.Test;
import akka.stream.javadsl.Source;
import akka.util.ByteString;
import play.mvc.Http.MultipartFormData.*;
import play.mvc.Http.RequestBuilder;
import play.mvc.Result;
import play.test.*;

class UploadFileTest extends WithApplication {
    @Test
    public void uploadTest() {
        Part<Source<ByteString, ?>> part = new FilePart<>("key", "fileName", "application/octet-stream",
                Source.empty());
        List<Part<Source<ByteString, ?>>> data = Arrays.asList(part);

        RequestBuilder requestBuilder = fakeRequest(controllers.routes.UploadController.upload()).method(POST)
                .bodyMultipart(data, mat);

        Result result = route(app, requestBuilder);

        assertEquals(Helpers.OK, result.status());
    }
}

如果你想发送非空文件,
而不是Source.empty()使用FileIO.fromFile(new File("path/to/file"));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2013-12-30
    相关资源
    最近更新 更多