1

对于 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>>() {});

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

其他有用信息

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

示例响应

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

2 回答 2

2

你有几个选择:

如果您只需要该User对象实例,则可以通过retrieve()第二个参数是域类(User在您的情况下)的方法来完成,然后您可以user根据需要使用该变量:

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

assertThat(user)
    .isNotNull()
    .extracting(User::getName)
    .isEqualTo("sample");

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

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。用户位于加载程序“app”的未命名模块中)

于 2020-04-28T10:52:00.200 回答
0

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

于 2020-11-25T10:55:52.850 回答