Micronaut HTTP 客户端 - 反序列化通用类型 - 用于 API 测试

Micronaut HTTP Client - Deserialize generic type - For API Testing

对于 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 检索方法吗?或者以任何其他方式将通用 class 类型与 HttpClient.

一起使用

其他有用信息

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

响应示例

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

您有几个选择:

如果您只需要那个 User 对象实例,您可以通过 retrieve() 方法来实现,其中第二个参数是域 class(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");

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

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: class java.util.LinkedHashMap cannot be cast to class my.app.domain.User (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; my.app.domain.User.User is in unnamed module of loader 'app')

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