Scala PlayFramework测试:在假请求错误中上载文件

Scala PlayFramework测试:在假请求错误中上载文件,scala,testing,playframework,Scala,Testing,Playframework,我想测试我的方法,这需要上传一个文件。它的初始化方式如下: 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) v

我想测试我的方法,这需要上传一个文件。它的初始化方式如下:

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())
我把它传给了骗子:

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]

我做错了什么?如何修复?我在互联网上查找,没有找到任何有用的方法来理解和解决这个问题。

路由
对于给定的
请求[T]
需要一个类型为
可写[T]
的隐式参数,该参数知道如何序列化请求体,因为它实际上会调用控制器操作,就像实际的web请求一样,将字节推送到控制器上

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

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

  • 编写自己的
    Writeable
    ,将
    MultipartFormData
    序列化为字节
  • 跳过路由部分,直接调用操作,如中的接受答案。这种测试操作的方法采用了一种快捷方式,实际上不会序列化和反序列化请求

  • 我认为第一种选择是付出太多的痛苦换来的收获,但是如果你沿着这条路走下去,也许会在你成功的时候贡献它。

    记住http请求完全是文本的,这一点很重要
    route()
    采用隐式的
    可写的
    将所提供请求的正文类型转换为文本。如果没有正确的
    可写
    ,就无法知道如何将
    MultipartFormData
    转换为请求主体

    似乎没有,但你可以自己提供。jroper有一个可供参考的示例。(编辑:该代码有缺陷,下面是示例)

    一旦您的
    是可写的
    ,您就需要使调用
    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]]])
    

    或者使您的
    可写
    a
    可写[AnyContentAsMultipartFormData]

    可能的解决方案之一是使用
    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"
     }
    }
    

    请你把错误贴出来好吗?废话。抄错了行。感谢您注意到可能的重复,我没有发现它有用,因为答案不是关于这个错误及其原因。回答问题的人只是用另一种方式进行测试,没有任何解释。我不想做单元测试,我需要解决这个错误!可能是重复的好吧,谢谢你把这些答案复制粘贴,我都看到了。我不想像那个问题的公认答案那样进行单元测试。我不确定你认为我是从哪里复制粘贴这些选项的。实际上,我花了整整十五分钟的空闲时间阅读play test helper源代码,为您找到答案。但是非常欢迎你,祝你好运!这是一个,也是你提到的一个。这是AnyContentsMultipartFormData AnyContentsMultipartFormData fongmun.com域的可写工作,它似乎已经失效,当前要求访问者安装一个粗略的浏览器扩展。太糟糕了,代码没有粘贴到GitHub gist或类似文件中。