2015-04-17 67 views
4

我想测试我的方法,该方法需要上传文件。它被初始化这样的: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) 
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] 

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

+1

您会发布错误吗? –

+0

废话。复制错误的行。感谢您注意 – Ophelia

+0

[在FakeRequest中使用MultipartFormData播放框架测试](http:// stackoverflow。com/questions/19658766/play-framework-testing-using-multipartformdata-in-a-fakerequest) –

回答

3

route对于给定Request[T]需要知道如何序列化的请求主体,因为它实际上将调用控制器动作就像是一个实际的web请求Writeable[T]类型的隐含参数会,通过推动字节到它。

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

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

  1. 写自己的Writeable序列化一个MultipartFormData成字节
  2. 跳过路由部分,并呼吁行动,而不是直接,就像在Play Framework Testing using MultipartFormData in a FakeRequest接受的答案。这种测试动作的方式采用了一种快捷方式,并不实际序列化和反序列化请求。

恕我直言,第一个选项对于增益来说太痛苦了,但是如果你沿着这条路走下去,也许可以在成功时发挥它的作用。

+0

,感谢复制粘贴这些答案,我看到了这一切。我不想通过单元测试,就像那个问题的接受答案一样。 – Ophelia

+0

我不确定你在哪里复制粘贴这些选项。实际上,我花了十五分钟时间阅读游戏测试帮助程序源代码,为您找到答案。但是,你非常欢迎,祝你好运! – johanandren

+0

http://stackoverflow.com/questions/15013177/serializing-multipart-form-requests-for-testing-on-play-2-1这一个,还有你提到的那个。 – Ophelia

5

请务必记住,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]

+0

以下是适用于AnyContentAsMultipartFormData的Writeable AnyContentAsMultipartFormData http://tech.fongmun.com/post/125479939452/test-multipartformdata-in-play – Tanin

1

其中一个可能的解决方案是使用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" 
} 
} 
相关问题