For API testing I have to parse the response of a request using io.micronaut.http.client.HttpClient
I prefer to use the format given below.
Response<User> response = client.toBlocking().retrieve(HttpRequest.POST("/", user), Response.class);
But It is not working. I am getting type cast error while trying to fetch User from response
User user = response.getUser();
Currently I am using ObjectMapper (Jackson) like given below,
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 there any way to use TypeReference directly with HttpClient retrieve method? Or any other way to use generic class type with HttpClient.
Other useful informations
// Response generic class class Response<T> { T data; .... }
Sample response
{ "data": { "name":"sample" }, "message": "Success" }
Advertisement
Answer
You have several options:
If you need only that User
object instance you can do it by retrieve()
method where the second parameter is the domain class (User
in your case) and then you can use the user
variable as you need:
User user = client.toBlocking().retrieve(HttpRequest.POST("/", user), User.class); assertThat(user) .isNotNull() .extracting(User::getName) .isEqualTo("sample");
If you need also response object (for example to be able to check response code) then you should use exchange()
method and then get the User
instance by calling body()
method on that response:
HttpResponse<User> response = client.toBlocking() .exchange(HttpRequest.POST("/", user), User.class); assertThat(response) .isNotNull() .extracting(HttpResponse::body) .extracting(User::getName) .isEqualTo("sample");
Update: When you need to use generic class as a response then you have to use Argument.of()
as a second parameter of the retrieve()
and exchange()
methods where you can specify response generic class and its type parameters. See the example:
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");
If you do it without Argument.of()
then it will convert data
property into LinkedHashMap
instead of User
and this:
Response<User> response = client.toBlocking().retrieve(HttpRequest.POST("/", user), Response.class); response.getData().getName();
… will throw 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’)