繁体   English   中英

如何从 ServerResponse 获取 body 作为 String 进行测试?

[英]How to get body as String from ServerResponse for test?

假设我们有一个oswreactive.function.server.ServerResponse实例。

获取其主体内容的正确方法是什么,换句话说,如何实现fetchBodyAsString function?

test(){
  ServerResponse response = getResponseFromService("mock data");

  String body = fetchBodyAsString(response);

  assertEquals("hello", body);
}

您能否详细说明为什么ServerResponse对所有内容( cookies(), headers(), statusCode() )都有方法,但响应主体除外? 我想应该有一种方法可以使用writeTo()方法获取正文,尽管如何使用它绝对是模糊的。

据我所知ServerResponse用于控制器或路由器功能。 对于测试,您可以使用WebTestClient

@Autowired
WebTestClient webTestClient;


@Test
void test() {

    webTestClient.get()
            .exchange()
            .expectStatus()
            .isOk()
            .expectHeader()
            .contentType(MediaType.APPLICATION_JSON)
            .expectBody()
            .jsonPath("data.name").isEqualTo("name");


}

或者

@Autowired
WebTestClient webTestClient;


@Test
void test() {

    FluxExchangeResult<String> result = webTestClient.get()
            .exchange()
            .returnResult(String.class);

    int rawStatusCode = result.getRawStatusCode();
    HttpStatus status = result.getStatus();
    HttpHeaders responseHeaders = result.getResponseHeaders();
    String stringResponseBody = result.getResponseBody().blockFirst();

}

为了单元测试目的,我正在寻找类似的东西,并将下面的代码拼接在一起。 它在 Kotlin 中,但应该相对容易转换为 Java 并解决您的问题(尽管它看起来确实有点笨拙)。

    fun fetchBodyAsString(serverResponse: ServerResponse): String {
        val DEFAULT_CONTEXT: ServerResponse.Context = object : ServerResponse.Context {
            override fun messageWriters(): List<HttpMessageWriter<*>> {
                return HandlerStrategies.withDefaults().messageWriters()
            }

            override fun viewResolvers(): List<ViewResolver> {
                return Collections.emptyList()
            }
        }

        // Only way I could figure out how to get the ServerResponse body was to have it write to an exchange
        val request = MockServerHttpRequest.get("http://thisdoenstmatter.com").build()
        val exchange = MockServerWebExchange.from(request)
        serverResponse.writeTo(exchange, DEFAULT_CONTEXT).block()
        val response = exchange.response
        return response.bodyAsString.block()!!
    }

基本上需要创建一个假的MockServerWebExchange并将ServerResponse写入它以将其转换为MockServerHttpResponse ,您可以MockServerHttpResponse费力地从中提取响应主体。 这绝对不优雅,但它有效。

另请注意,我没有测试上述函数本身,只是它可以编译。 它应该可以工作,因为函数的内部代码正是我们正在使用的。

至于您关于ServerResponse的其他问题,我不知道答案,但对此也很好奇!

这是基于 Alan Yeung 上面的解决方案,Java 除外。 必须有一种更好的“本机”方式来做到这一点,而无需加载应用程序上下文。

public class ServerResponseExtractor {

  public static <T> T serverResponseAsObject(ServerResponse serverResponse,
      ObjectMapper mapper, Class<T> type) {
    String response = serverResponseAsString(serverResponse);
    try {
      return mapper.readValue(response, type);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
  }

  public static String serverResponseAsString(ServerResponse serverResponse) {
    MockServerWebExchange exchange = MockServerWebExchange.from(
            MockServerHttpRequest.get("/foo/foo"));

    DebugServerContext debugServerContext = new DebugServerContext();
    serverResponse.writeTo(exchange, debugServerContext).block();

    MockServerHttpResponse response = exchange.getResponse();
    return response.getBodyAsString().block();

  }

  private static class DebugServerContext implements ServerResponse.Context {
    @Override
    public List<HttpMessageWriter<?>> messageWriters() {
      return HandlerStrategies.withDefaults().messageWriters();
    }
    @Override
    public List<ViewResolver> viewResolvers() {
      return Collections.emptyList();
    }
  }

}

在单元测试中测试正文的另一种方法是将ServerResponse转换为EntityResponse 这确实显示了对未经检查的转换的警告,但在受控单元测试中我并不太担心。 这只是公开了在序列化之前使用bodyValue()设置的 object。 如果您正在尝试测试所述主体的序列化,这可能无法满足您的需求。

val entityResponse = serverResponse as EntityResponse<{ Insert Class of Body }>
val bodyObject = entityResponse.entity()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM