HTTP-клиент Micronaut - десериализация типа generi c - для тестирования API - PullRequest
0 голосов
/ 28 апреля 2020

Для тестирования API я должен проанализировать ответ на запрос, используя io.micronaut.http.client.HttpClient

Я предпочитаю использовать формат, приведенный ниже.

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

Но Это не работает. Я получаю ошибку приведения типа при попытке извлечь пользователя из ответа

User user = response.getUser();

В настоящее время я использую ObjectMapper (Джексон), как указано ниже,

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

Is Есть ли способ использовать TypeReference напрямую с HttpClient метод получения? Или любой другой способ использовать тип класса generi c с HttpClient .

Другая полезная информация

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

Пример ответа

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

1 Ответ

1 голос
/ 28 апреля 2020

У вас есть несколько вариантов:

Если вам нужен только этот 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");

Обновление : когда вам нужно использовать класс generi c как Затем в качестве ответа вы должны использовать Argument.of() в качестве второго параметра методов retrieve() и exchange(), где вы можете указать класс ответа generi c и параметры его типа. См. Пример:

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 находится в модуле java .base загрузчика 'bootstrap'; my.app.domain.User.User находится в безымянном модуле загрузчика 'app')

...