【问题标题】:PlayFramework Testing: Uploading File in Fake Request ErrorsPlayFramework 测试:在虚假请求错误中上传文件
【发布时间】:2017-01-20 18:54:22
【问题描述】:

我想测试我的方法,该方法需要上传文件。它是这样初始化的:

val tempFile = TemporaryFile(new java.io.File("/home/ophelia/Desktop/students"))
val part = FilePart[TemporaryFile](
  key = "students", 
  filename = "students", 
  contentType = Some("text/plain"), 
  ref = tempFile)
val files = Seq[FilePart[TemporaryFile]](part)
val formData = MultipartFormData(
  dataParts = Map(), 
  files = Seq(part), 
  badParts = Seq(), 
  missingFileParts = Seq())

我将它传递给 FakeRequest:

val result = route(
  FakeRequest(POST, "/api/courses/"+"4f3c4ec9-46bf-4a05-a0b2-886c2040f2f6"+"/import" )
    .withHeaders("Authorization" -> ("Session " + testSessionA.id.string))
    .withMultipartFormDataBody(formData)
)

但是当我运行测试时出现以下错误:

Cannot write an instance of play.api.mvc.AnyContentAsMultipartFormData to HTTP response. Try to define a Writeable[play.api.mvc.AnyContentAsMultipartFormData]

我做错了什么以及如何解决?我上网查了一下,没有找到任何有用的方法来理解和解决这个问题。

【问题讨论】:

标签: scala testing playframework


【解决方案1】:

请务必记住,http 请求完全是文本。 route() 采用隐式 Writeable 将所提供请求的正文类型转换为文本。没有正确的Writeable,就无法知道如何将MultipartFormData变成请求体。

似乎没有Writeable for MultipartFormData,但您可以提供自己的。 jroper 有一个 great Writeable 供您参考。 (编辑:那个代码有问题,这里是a working Writeable for AnyContentAsMultipartFormData

拥有Writeable 后,您需要将其提供给您对route() 的调用。请记住,您目前拥有的是FakeRequest[AnyContentAsMultipartFormData],而不是FakeRequest[MultipartFormData]。您可以先转换您的请求:

val request = FakeRequest(POST, 
    "/api/courses/"+"4f3c4ec9-46bf-4a05-a0b2-886c2040f2f6"+"/import" )
        .withHeaders("Authorization" -> ("Session "))
        .withMultipartFormDataBody(formData)
route(request.map(_.mdf).asInstanceOf[FakeRequest[MultipartFormData[TemporaryFile]]])

或将您的 Writeable 设为 Writeable[AnyContentAsMultipartFormData]

【讨论】:

  • 这是 AnyContentAsMultipartFormData AnyContentAsMultipartFormData tech.fongmun.com/post/125479939452/… 的工作可写
  • fongmun.com 域似乎已经失效,目前要求访问者安装粗略的浏览器扩展程序。太糟糕了,代码没有粘贴到 GitHub gist 或类似的地方。
【解决方案2】:

route 对于给定的Request[T] 需要一个 Writeable[T] 类型的隐式参数,它知道如何序列化请求正文,因为它实际上会像实际的 Web 请求一样调用控制器操作,通过将字节推送到它。

问题是没有预定义的Writeable[MultipartFormData](你可以看到play.api.test.Writeables中有哪些)。

这意味着您基本上有两种选择:

  1. 编写您自己的Writeable,将MultipartFormData 序列化为字节
  2. 跳过路由部分并直接调用操作,就像在Play Framework Testing using MultipartFormData in a FakeRequest 中接受的答案中一样。这种测试操作的方式走捷径,实际上并不序列化和反序列化请求。

恕我直言,第一种选择是太痛苦了,但如果你走这条路,当你成功时,也许可以贡献它。

【讨论】:

  • 好吧,感谢您复制粘贴这些答案,我都看到了。我不想像接受该问题的答案那样进行单元测试。
  • 我不确定你认为我从哪里复制粘贴了这些选项。实际上,我花了 15 分钟的空闲时间阅读游戏测试助手源代码来为您找到答案。但是非常欢迎你,祝你好运!
  • stackoverflow.com/questions/15013177/…这个,还有你提到的那个。
【解决方案3】:

一种可能的解决方案是使用wsUrl。例如

"File uploading action" should {

  "upload sent file and result in ID" in {
    val file = Paths.get(getClass.getResource("/1.txt").toURI)
    val action = wsUrl("/upload").post(Source.single(FilePart("file", "hello.txt", Option("text/plain"), FileIO.fromPath(file))))

    val res = Await.result(action, timeout)

    res.status mustBe OK
    res.body contains "123"
 }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    相关资源
    最近更新 更多