Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法使用scalamock模拟WSRequest.post()_Scala_Playframework_Scalamock_Play Ws - Fatal编程技术网

无法使用scalamock模拟WSRequest.post()

无法使用scalamock模拟WSRequest.post(),scala,playframework,scalamock,play-ws,Scala,Playframework,Scalamock,Play Ws,我正在使用Scalamock和Scalatest为Play应用程序编写单元测试 我的原始代码如下所示: // Here ws is an injected WSClient val req = Json.toJson(someRequestObject) val resp: Future[WSResponse] = ws.url(remoteURL).post(Json.toJson(req)) 在一部分中,我必须模拟对web服务的外部调用,我正试图使用scalamock来实现这一点: ws

我正在使用Scalamock和Scalatest为Play应用程序编写单元测试

我的原始代码如下所示:

// Here ws is an injected WSClient
val req = Json.toJson(someRequestObject)
val resp: Future[WSResponse] = ws.url(remoteURL).post(Json.toJson(req))
在一部分中,我必须模拟对web服务的外部调用,我正试图使用scalamock来实现这一点:

ws = stub[WSClient]
wsReq = stub[WSRequest]
wsResp = stub[WSResponse]

ws.url _ when(*) returns wsReq
wsReq.withRequestTimeout _ when(*) returns wsReq
(wsReq.post (_: java.io.File)).when(*) returns Future(wsResp)
我能够成功地使用文件模拟post请求,但无法使用JSON模拟post请求

我尝试分别放置存根函数引用,如:

val f: StubFunction1[java.io.File, Future[WSResponse]] = wsReq.post (_: java.io.File)

val j: StubFunction1[JsValue, Future[WSResponse]] = wsReq.post(_: JsValue)
我得到第二行的编译错误:
无法解析重载的方法post


我错过了什么?为什么我不能模拟一个重载方法,而不能模拟另一个方法?

play.api.libs.ws.WSRequest
有两个
post
方法(),分别是:

  • 文件
  • T
    (其中
    T
    对可写的
    有一个隐式边界)
  • 编译器失败,因为您试图使用一个仅与版本1匹配的参数调用
    post
    。但是,
    JsValue
    不能替换为
    文件

    实际上,您希望调用第二个版本,但这是一个采用两组参数的curried方法(尽管第二个是隐式的)。因此,您需要显式地提供您期望隐式的模拟值,即

    val j:StubFunction1[JsValue,Future[WSResponse]]=wsReq.post(quo:JsValue)(隐式[Writeable[JsValue]])

    因此,一个有效的解决办法是:

    (wsReq.post()())。当(*)返回Future(wsResp)

    旧答案:

    WSRequest
    提供了
    post
    方法()的4个重载,其中包括:

  • String
  • JsonNode
  • InputStream
  • 文件

  • 您可以使用
    文件进行模拟,因为它匹配重载4,但
    JsValue
    不匹配(这是Play JSON模型的一部分,而
    JsonNode
    是Jackson JSON模型的一部分)。如果您转换为
    字符串
    JsonNode
    ,那么它将解决正确的重载并进行编译。

    我的最佳猜测是,您的
    WSRequest
    实际上是一个
    play.libs.ws.WSRequest
    ,它是Java API的一部分,而您应该使用
    play.API.libs.ws.WSRequest
    ,它是Scala API

    该方法存在并由Scala API中的
    WSBodyWritables
    隐式提供,但不在Java API中


    另一个原因可能是您的
    JsValue
    不是一个
    play.api.libs.json.JsValue
    ,而是其他东西(例如
    spray.json.JsValue
    )。

    我将引用一个成功实现您尝试的示例,主要区别是我使用了
    mock
    而不是
    stub

    重要的部分是:

    val ws = mock[WSClient]
    val responseBody = "{...}"
    ...
    "availableBooks" should {
      "retrieve available books" in {
        val expectedBooks = "BTC_DASH ETH_DASH USDT_LTC BNB_LTC".split(" ").map(Book.fromString).map(_.get).toList
    
        val request = mock[WSRequest]
        val response = mock[WSResponse]
        val json = Json.parse(responseBody)
    
        when(ws.url(anyString)).thenReturn(request)
        when(response.status).thenReturn(200)
        when(response.json).thenReturn(json)
        when(request.get()).thenReturn(Future.successful(response))
    
        whenReady(service.availableBooks()) { books =>
          books.size mustEqual expectedBooks.size
    
          books.sortBy(_.string) mustEqual expectedBooks.sortBy(_.string)
        }
      }
    }
    

    您可以在以下位置看到完整的测试:

    我想如果您模拟一个JsValue响应,它应该可以正常工作

    when(wsReq.post(Json.parse("""{...json request...}"""))).thenReturn(Future(wsResp))
    

    这里
    Json.parse
    返回
    JsValue
    。您应该在请求正文中传递您期望的json字符串。

    谢谢Woodz。这个问题对于Scala来说非常特殊。它没有用于JsonNode的重载方法。这里假定的过度使用是:
    def post[T](body:T)(隐式arg0:bodywriteable[T]):Future[Response]
    Thank@Xolve-我没有注意到您使用的是Scala Play ApiThank@J0HN。你的回答为我提供了我所需要的:)尽管实际的解决方案与应该的有点不同。1.需要显式类型。2.需要两个通配符参数。它看起来像:
    (wsReq.post(:JsValue)(:bodywriteable[JsValue])当(*,*)返回Future(wsResp)
    时,您是如何得出包含隐式表达式的结论的?在post方法的声明中,没有这样的东西:
    override def post[T:bodywriteable](body:T):Future[Response]
    @Xolve Scala中的上下文绑定是泛型类型上专用的该类型的隐式参数的语法糖。例如,
    post[T:BodyWriteable]
    post[T](隐式证据$0:BodyWriteable[T])
    ()相同,您尝试过吗?