【问题标题】:Micronaut HTTP Client - Deserialize generic type - For API TestingMicronaut HTTP 客户端 - 反序列化泛型类型 - 用于 API 测试
【发布时间】:2020-04-28 09:11:32
【问题描述】:

对于 API 测试,我必须使用 io.micronaut.http.client.HttpClient 解析请求的响应

我更喜欢使用下面给出的格式。

Response<User> response =
                client.toBlocking().retrieve(HttpRequest.POST("/", user), Response.class);

但它不起作用。我在尝试从响应中获取用户时遇到类型转换错误

User user = response.getUser();

目前我正在使用 ObjectMapper (Jackson),如下所示,

String response = client.toBlocking().retrieve(HttpRequest.POST("/", user), String.class);
ObjectMapper objectMapper = new ObjectMapper();
Response<User> response = objectMapper.readValue(response, new TypeReference<Response<User>>() {});

有没有办法直接使用 TypeReferenceHttpClient 检索方法?或以任何其他方式将泛型类类型与 HttpClient 一起使用。

其他有用的信息

// Response generic class
class Response<T> {
T data;
....
}

示例响应

{
    "data": {
        "name":"sample"
    },
    "message": "Success"
}

【问题讨论】:

    标签: java junit jackson micronaut micronaut-client


    【解决方案1】:

    您有多种选择:

    如果您只需要 User 对象实例,您可以通过 retrieve() 方法来实现,其中第二个参数是域类(在您的情况下为 User),然后您可以使用 user 变量作为您需要:

    User user = client.toBlocking().retrieve(HttpRequest.POST("/", user), User.class);
    
    assertThat(user)
        .isNotNull()
        .extracting(User::getName)
        .isEqualTo("sample");
    

    如果您还需要响应对象(例如能够检查响应代码),那么您应该使用 exchange() 方法,然后通过在该响应上调用 body() 方法来获取 User 实例:

    HttpResponse<User> response = client.toBlocking()
        .exchange(HttpRequest.POST("/", user), User.class);
    
    assertThat(response)
        .isNotNull()
        .extracting(HttpResponse::body)
        .extracting(User::getName)
        .isEqualTo("sample");
    

    更新:当您需要使用泛型类作为响应时,您必须使用Argument.of() 作为retrieve()exchange() 方法的第二个参数,您可以在其中指定响应泛型类及其类型参数。看例子:

    Response<User> response = client.toBlocking()
        .retrieve(HttpRequest.POST("/", user), Argument.of(Response.class, User.class));
    
    assertThat(response)
        .isNotNull()
        .extracting(Response::getData)
        .extracting(User::getName)
        .isEqualTo("sample");
    

    如果您在没有Argument.of() 的情况下执行此操作,那么它会将data 属性转换为LinkedHashMap 而不是User,这样:

    Response<User> response = client.toBlocking().retrieve(HttpRequest.POST("/", user), Response.class);
    response.getData().getName();
    

    ...会抛出ClassCastException:

    java.lang.ClassCastException:类 java.util.LinkedHashMap 不能 转换为 my.app.domain.User 类(java.util.LinkedHashMap 在模块中 加载程序'bootstrap'的java.base; my.app.domain.User.User 未命名 加载器'app'的模块)

    【讨论】:

    • 您好,感谢您的回答。 Response 是一个自定义泛型类,用于包装 api 响应。因此,所讨论的反序列化 api 响应的正确类型是 Response。例如。响应类 Response{ T 数据; } 我想从 Response 类型中提取数据字段。
    • 好的,抱歉,我误解了你的问题。所以我还添加了一个带有泛型类的示例作为响应。
    【解决方案2】:

    就像一个非常简单的替代方案:当您的响应是 JSON 时,您总是可以简单地将它们反序列化为 Map.class。快速简单。当然,你没有类型安全。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-18
      • 2013-08-26
      • 2023-03-05
      • 2012-07-24
      相关资源
      最近更新 更多