如何从 Play WSClient 的字符串创建 WSResponse object

How to create a WSResponse object from string for Play WSClient

Documentation 建议使用模拟 Web 服务测试基于 WSClient 的 API 客户端,即创建一个 play.server.Server 来响应真实的 HTTP 请求。

我更愿意直接从文件创建 WSResponse objects,完成状态行、header 行和 body,而不需要真正的 TCP 连接。这将需要更少的依赖性并且 运行 更快。在其他情况下也可能有用。

但我找不到简单的方法来做到这一点。 WSResponse 包装的所有实现似乎都与从网络读取有关。

我应该为此创建自己的 WSResponse 子类,还是我错了,它已经存在了?

Play 的 API 似乎有意变得迟钝。您必须使用它们的 "Cacheable" 类,它们是唯一可以直接从 objects 实例化的对象。

这应该让你开始:

import play.api.libs.ws.ahc.AhcWSResponse;
import play.api.libs.ws.ahc.cache.CacheableHttpResponseBodyPart;
import play.api.libs.ws.ahc.cache.CacheableHttpResponseHeaders;
import play.api.libs.ws.ahc.cache.CacheableHttpResponseStatus;
import play.shaded.ahc.io.netty.handler.codec.http.DefaultHttpHeaders;
import play.shaded.ahc.org.asynchttpclient.Response;
import play.shaded.ahc.org.asynchttpclient.uri.Uri;

AhcWSResponse response = new AhcWSResponse(new Response.ResponseBuilder()
        .accumulate(new CacheableHttpResponseStatus(Uri.create("uri"), 200, "status text", "protocols!"))
        .accumulate(new CacheableHttpResponseHeaders(false, new DefaultHttpHeaders().add("My-Header", "value")))
        .accumulate(new CacheableHttpResponseBodyPart("my body".getBytes(), true))
        .build());

未记录神秘的布尔值。我的猜测是 BodyPart 的布尔值是它是否是 body 的最后一部分。我对 Headers 的猜测是 headers 是否在消息的尾部。

我用了另一种方式,用Mockito模拟WSResponse:

import play.libs.ws.WSRequest;
import play.libs.ws.WSResponse;
import org.mockito.Mockito;

...

          final WSResponse wsResponseMock = Mockito.mock(WSResponse.class);
          Mockito.doReturn(200).when(wsResponseMock).getStatus();
          final String jsonStr = "{\n"
                  + "  \"response\": {\n"
                  + "    \"route\": [\n"
                  + "      { \"summary\" :\n"
                  + "        {\n"
                  + "          \"distance\": 23\n"
                  + "        }\n"
                  + "      }\n"
                  + "    ]\n"
                  + "  }\n"
                  + "}";
          ObjectMapper mapper = new ObjectMapper();
          JsonNode jsonNode = null;
          try {
            jsonNode = mapper.readTree(jsonStr);
          } catch (IOException e) {
            e.printStackTrace();
          }
          Mockito.doReturn(
                  jsonNode)
              .when(wsResponseMock)
              .asJson();

如果您正在使用 play-framework 2.8.xscala,下面的代码可以帮助我们生成一个虚拟 WSResponse:

import play.api.libs.ws.ahc.AhcWSResponse
import play.api.libs.ws.ahc.cache.CacheableHttpResponseStatus
import play.shaded.ahc.org.asynchttpclient.Response
import play.shaded.ahc.org.asynchttpclient.uri.Uri
import play.api.libs.ws.ahc.cache.CacheableHttpResponseBodyPart
import play.shaded.ahc.io.netty.handler.codec.http.DefaultHttpHeaders

class OutputWriterSpec extends FlatSpec with Matchers {
  val respBuilder = new Response.ResponseBuilder()
  respBuilder.accumulate(new CacheableHttpResponseStatus(Uri.create("http://localhost:9000/api/service"), 202, "status text", "json"))
  respBuilder.accumulate(new DefaultHttpHeaders().add("Content-Type", "application/json"))
  respBuilder.accumulate(new CacheableHttpResponseBodyPart("{\n\"id\":\"job-1\",\n\"lines\": [\n\"62812ce276aa9819a2e272f94124d5a1\",\n\"13ea8b769685089ba2bed4a665a61fde\"\n]\n}".getBytes(), true))
  val resp = new AhcWSResponse(respBuilder.build())

  val outputWriter = OutputWriter

  val expected = ("\"job-1\"", List("\"62812ce276aa9819a2e272f94124d5a1\"", "\"13ea8b769685089ba2bed4a665a61fde\""), "_SUCCESS")
  "Output Writer" should "handle response from api call" in {
    val actual = outputWriter.handleResponse(resp, "job-1")
    println("the actual : " + actual)
    actual shouldEqual(expected)

  }
}