From df31e606c3d8486dfb99a0be50491e74097b2810 Mon Sep 17 00:00:00 2001 From: Trixi Turny Date: Sat, 9 Jan 2021 15:55:24 +0000 Subject: [PATCH 1/4] BAEL-4748 implement UserConsumerService with webClient and write UnitTests --- .../webclient/json/UserConsumerService.java | 16 ++++ .../json/UserConsumerServiceImpl.java | 90 +++++++++++++++++++ .../webclient/json/model/Address.java | 29 ++++++ .../baeldung/webclient/json/model/User.java | 30 +++++++ .../json/UserConsumerServiceImplUnitTest.java | 74 +++++++++++++++ 5 files changed, 239 insertions(+) create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java new file mode 100644 index 0000000000..9afc207ff2 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java @@ -0,0 +1,16 @@ +package com.baeldung.webclient.json; + +import java.util.List; + +public interface UserConsumerService { + + List processUserDataFromObjectArray(); + + List processUserDataFromUserArray(); + + List processUserDataFromUserList(); + + List processNestedUserDataFromUserArray(); + + List processNestedUserDataFromUserList(); +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java new file mode 100644 index 0000000000..30cd4a5617 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java @@ -0,0 +1,90 @@ +package com.baeldung.webclient.json; + +import com.baeldung.webclient.json.model.Address; +import com.baeldung.webclient.json.model.User; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class UserConsumerServiceImpl implements UserConsumerService { + + private final WebClient webClient; + private static final ObjectMapper mapper = new ObjectMapper(); + + public UserConsumerServiceImpl(WebClient webClient) { + this.webClient = webClient; + } + @Override + public List processUserDataFromObjectArray() { + Mono response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Object[].class).log(); + Object[] objects = response.block(); + return Arrays.stream(objects) + .map(object -> mapper.convertValue(object, User.class)) + .map(User::getName) + .collect(Collectors.toList()); + } + + @Override + public List processUserDataFromUserArray() { + Mono response = + webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(User[].class).log(); + + User[] userArray = response.block(); + return Arrays.stream(userArray) + .map(User::getName) + .collect(Collectors.toList()); + } + + @Override + public List processUserDataFromUserList() { + Mono> response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}); + List userList = response.block(); + + return userList.stream() + .map(User::getName) + .collect(Collectors.toList()); + } + + @Override + public List processNestedUserDataFromUserArray() { + Mono response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(User[].class).log(); + User[] userArray = response.block(); + + return Arrays.stream(userArray) + .flatMap(user -> user.getAddressList().stream()) + .map(Address::getPostCode) + .collect(Collectors.toList()); + } + + @Override + public List processNestedUserDataFromUserList() { + Mono> response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}); + + List userList = response.block(); + return userList.stream() + .flatMap(user -> user.getAddressList().stream()) + .map(Address::getPostCode) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java new file mode 100644 index 0000000000..cc4323b72b --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java @@ -0,0 +1,29 @@ +package com.baeldung.webclient.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Address { + private final String addressLine1; + private final String addressLine2; + private final String town; + private final String postCode; + + @JsonCreator + public Address( + @JsonProperty("addressLine1") String addressLine1, + @JsonProperty("addressLine2") String addressLine2, + @JsonProperty("town") String town, + @JsonProperty("postCode") String postCode) { + this.addressLine1 = addressLine1; + this.addressLine2 = addressLine2; + this.town = town; + this.postCode = postCode; + } + public String getPostCode() { + return postCode; + } +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java new file mode 100644 index 0000000000..6ed359f9db --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java @@ -0,0 +1,30 @@ +package com.baeldung.webclient.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class User { + private final int id; + private final String name; + private final List
addressList; + + @JsonCreator + public User( + @JsonProperty("id") int id, + @JsonProperty("name") String name, + @JsonProperty("addressList") List
addressList) { + this.id = id; + this.name = name; + this.addressList = addressList; + } + + public String getName() { + return name; + } + + public List
getAddressList() { return addressList; } +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java new file mode 100644 index 0000000000..151554efde --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java @@ -0,0 +1,74 @@ +package com.baeldung.webclient.json; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; + +public class UserConsumerServiceImplUnitTest { + + private static String USER_JSON = "[{\"id\":1,\"name\":\"user1\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user1_address1_postCode\"}," + + "{\"addressLine1\":\"address2_addressLine1\",\"addressLine2\":\"address2_addressLine2\",\"town\":\"address2_town\",\"postCode\":\"user1_address2_postCode\"}]}," + + "{\"id\":2,\"name\":\"user2\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user2_address1_postCode\"}]}]"; + + private static String BASE_URL = "http://localhost:8080"; + + WebClient webClientMock = WebClient.builder() + .exchangeFunction(clientRequest -> Mono.just(ClientResponse.create(HttpStatus.OK) + .header("content-type", "application/json") + .body(USER_JSON) + .build())) + .build(); + + private final UserConsumerService tested = new UserConsumerServiceImpl(webClientMock); + + @Test + void when_processUserDataFromObjectArray_then_OK() { + List expected = Arrays.asList("user1", "user2"); + List actual = tested.processUserDataFromObjectArray(); + assertThat(actual, contains(expected.get(0), expected.get(1))); + } + + @Test + void when_processUserDataFromUserArray_then_OK() { + List expected = Arrays.asList("user1", "user2"); + List actual = tested.processUserDataFromUserArray(); + assertThat(actual, contains(expected.get(0), expected.get(1))); + } + + @Test + void when_processUserDataFromUserList_then_OK() { + List expected = Arrays.asList("user1", "user2"); + List actual = tested.processUserDataFromUserList(); + assertThat(actual, contains(expected.get(0), expected.get(1))); + } + + @Test + void when_processNestedUserDataFromUserArray_then_OK() { + List expected = Arrays.asList( + "user1_address1_postCode", + "user1_address2_postCode", + "user2_address1_postCode"); + + List actual = tested.processNestedUserDataFromUserArray(); + assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2))); + } + + @Test + void when_processNestedUserDataFromUserList_then_OK() { + List expected = Arrays.asList( + "user1_address1_postCode", + "user1_address2_postCode", + "user2_address1_postCode"); + + List actual = tested.processNestedUserDataFromUserList(); + assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2))); + } +} \ No newline at end of file From 70a0e0de969efdcb8da019e01a1ca122b47cb6e1 Mon Sep 17 00:00:00 2001 From: Trixi Turny Date: Sat, 23 Jan 2021 11:19:30 +0000 Subject: [PATCH 2/4] BAEL-4748 change user to reader and address to favouriteBooks --- .../webclient/json/ReaderConsumerService.java | 16 ++++ .../json/ReaderConsumerServiceImpl.java | 90 +++++++++++++++++++ .../webclient/json/UserConsumerService.java | 16 ---- .../json/UserConsumerServiceImpl.java | 90 ------------------- .../webclient/json/model/Address.java | 29 ------ .../baeldung/webclient/json/model/Book.java | 22 +++++ .../baeldung/webclient/json/model/Reader.java | 0 .../baeldung/webclient/json/model/User.java | 30 ------- .../ReaderConsumerServiceImplUnitTest.java | 77 ++++++++++++++++ .../json/UserConsumerServiceImplUnitTest.java | 74 --------------- 10 files changed, 205 insertions(+), 239 deletions(-) create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java delete mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java delete mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java delete mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Book.java create mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java delete mode 100644 spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java delete mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java new file mode 100644 index 0000000000..b0bc71d2ed --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java @@ -0,0 +1,16 @@ +package com.baeldung.webclient.json; + +import java.util.List; + +public interface ReaderConsumerService { + + List processReaderDataFromObjectArray(); + + List processReaderDataFromReaderArray(); + + List processReaderDataFromReaderList(); + + List processNestedReaderDataFromReaderArray(); + + List processNestedReaderDataFromReaderList(); +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java new file mode 100644 index 0000000000..d1800a7f65 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java @@ -0,0 +1,90 @@ +package com.baeldung.webclient.json; + +import com.baeldung.webclient.json.model.Book; +import com.baeldung.webclient.json.model.Reader; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class ReaderConsumerServiceImpl implements ReaderConsumerService { + + private final WebClient webClient; + private static final ObjectMapper mapper = new ObjectMapper(); + + public ReaderConsumerServiceImpl(WebClient webClient) { + this.webClient = webClient; + } + @Override + public List processReaderDataFromObjectArray() { + Mono response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Object[].class).log(); + Object[] objects = response.block(); + return Arrays.stream(objects) + .map(object -> mapper.convertValue(object, Reader.class)) + .map(Reader::getName) + .collect(Collectors.toList()); + } + + @Override + public List processReaderDataFromReaderArray() { + Mono response = + webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Reader[].class).log(); + + Reader[] readers = response.block(); + return Arrays.stream(readers) + .map(Reader::getName) + .collect(Collectors.toList()); + } + + @Override + public List processReaderDataFromReaderList() { + Mono> response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}); + List readers = response.block(); + + return readers.stream() + .map(Reader::getName) + .collect(Collectors.toList()); + } + + @Override + public List processNestedReaderDataFromReaderArray() { + Mono response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Reader[].class).log(); + Reader[] readers = response.block(); + + return Arrays.stream(readers) + .flatMap(reader -> reader.getFavouriteBooks().stream()) + .map(Book::getAuthor) + .collect(Collectors.toList()); + } + + @Override + public List processNestedReaderDataFromReaderList() { + Mono> response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}); + + List readers = response.block(); + return readers.stream() + .flatMap(reader -> reader.getFavouriteBooks().stream()) + .map(Book::getAuthor) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java deleted file mode 100644 index 9afc207ff2..0000000000 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.webclient.json; - -import java.util.List; - -public interface UserConsumerService { - - List processUserDataFromObjectArray(); - - List processUserDataFromUserArray(); - - List processUserDataFromUserList(); - - List processNestedUserDataFromUserArray(); - - List processNestedUserDataFromUserList(); -} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java deleted file mode 100644 index 30cd4a5617..0000000000 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/UserConsumerServiceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.baeldung.webclient.json; - -import com.baeldung.webclient.json.model.Address; -import com.baeldung.webclient.json.model.User; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public class UserConsumerServiceImpl implements UserConsumerService { - - private final WebClient webClient; - private static final ObjectMapper mapper = new ObjectMapper(); - - public UserConsumerServiceImpl(WebClient webClient) { - this.webClient = webClient; - } - @Override - public List processUserDataFromObjectArray() { - Mono response = webClient.get() - .accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono(Object[].class).log(); - Object[] objects = response.block(); - return Arrays.stream(objects) - .map(object -> mapper.convertValue(object, User.class)) - .map(User::getName) - .collect(Collectors.toList()); - } - - @Override - public List processUserDataFromUserArray() { - Mono response = - webClient.get() - .accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono(User[].class).log(); - - User[] userArray = response.block(); - return Arrays.stream(userArray) - .map(User::getName) - .collect(Collectors.toList()); - } - - @Override - public List processUserDataFromUserList() { - Mono> response = webClient.get() - .accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono(new ParameterizedTypeReference>() {}); - List userList = response.block(); - - return userList.stream() - .map(User::getName) - .collect(Collectors.toList()); - } - - @Override - public List processNestedUserDataFromUserArray() { - Mono response = webClient.get() - .accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono(User[].class).log(); - User[] userArray = response.block(); - - return Arrays.stream(userArray) - .flatMap(user -> user.getAddressList().stream()) - .map(Address::getPostCode) - .collect(Collectors.toList()); - } - - @Override - public List processNestedUserDataFromUserList() { - Mono> response = webClient.get() - .accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono(new ParameterizedTypeReference>() {}); - - List userList = response.block(); - return userList.stream() - .flatMap(user -> user.getAddressList().stream()) - .map(Address::getPostCode) - .collect(Collectors.toList()); - } -} \ No newline at end of file diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java deleted file mode 100644 index cc4323b72b..0000000000 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Address.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.webclient.json.model; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - - -@JsonInclude(JsonInclude.Include.NON_NULL) -public class Address { - private final String addressLine1; - private final String addressLine2; - private final String town; - private final String postCode; - - @JsonCreator - public Address( - @JsonProperty("addressLine1") String addressLine1, - @JsonProperty("addressLine2") String addressLine2, - @JsonProperty("town") String town, - @JsonProperty("postCode") String postCode) { - this.addressLine1 = addressLine1; - this.addressLine2 = addressLine2; - this.town = town; - this.postCode = postCode; - } - public String getPostCode() { - return postCode; - } -} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Book.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Book.java new file mode 100644 index 0000000000..cb3fb258d4 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Book.java @@ -0,0 +1,22 @@ +package com.baeldung.webclient.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Book { + private final String author; + private final String title; + + @JsonCreator + public Book( + @JsonProperty("author") String author, + @JsonProperty("title") String title) { + this.author = author; + this.title = title; + } + public String getAuthor() { + return this.author; + } +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java deleted file mode 100644 index 6ed359f9db..0000000000 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/User.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.webclient.json.model; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.List; - -@JsonInclude(JsonInclude.Include.NON_NULL) -public class User { - private final int id; - private final String name; - private final List
addressList; - - @JsonCreator - public User( - @JsonProperty("id") int id, - @JsonProperty("name") String name, - @JsonProperty("addressList") List
addressList) { - this.id = id; - this.name = name; - this.addressList = addressList; - } - - public String getName() { - return name; - } - - public List
getAddressList() { return addressList; } -} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java new file mode 100644 index 0000000000..92f7bf4f3f --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.webclient.json; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; + +public class ReaderConsumerServiceImplUnitTest { + + private static String READER_JSON = "[{\"id\":1,\"name\":\"reader1\",\"favouriteBooks\":[{\"author\":\"Milan Kundera\",\"title\":\"The Unbearable Lightness of Being\"}," + + "{\"author\":\"Charles Dickens\",\"title\":\"Oliver Twist\"}]}," + + "{\"id\":2,\"name\":\"reader2\",\"favouriteBooks\":[{\"author\":\"J.R.R. Tolkien\",\"title\":\"Lord of the Rings\"}, " + + "{\"author\":\"Douglas Adams\",\"title\":\"The Hitchhiker\'s Guide to the Galaxy\"}]}]"; + + private static String BASE_URL = "http://localhost:8080"; + + WebClient webClientMock = WebClient.builder() + .exchangeFunction(clientRequest -> Mono.just(ClientResponse.create(HttpStatus.OK) + .header("content-type", "application/json") + .body(READER_JSON) + .build())) + .build(); + + private final ReaderConsumerService tested = new ReaderConsumerServiceImpl(webClientMock); + + @Test + void when_processReaderDataFromObjectArray_then_OK() { + List expected = Arrays.asList("reader1", "reader2"); + List actual = tested.processReaderDataFromObjectArray(); + assertThat(actual, contains(expected.get(0), expected.get(1))); + } + + @Test + void when_processReaderDataFromReaderArray_then_OK() { + List expected = Arrays.asList("reader1", "reader2"); + List actual = tested.processReaderDataFromReaderArray(); + assertThat(actual, contains(expected.get(0), expected.get(1))); + } + + @Test + void when_processReaderDataFromReaderList_then_OK() { + List expected = Arrays.asList("reader1", "reader2"); + List actual = tested.processReaderDataFromReaderList(); + assertThat(actual, contains(expected.get(0), expected.get(1))); + } + + @Test + void when_processNestedReaderDataFromReaderArray_then_OK() { + List expected = Arrays.asList( + "Milan Kundera", + "Charles Dickens", + "J.R.R. Tolkien", + "Douglas Adams"); + + List actual = tested.processNestedReaderDataFromReaderArray(); + assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); + } + + @Test + void when_processNestedReaderDataFromReaderList_then_OK() { + List expected = Arrays.asList( + "Milan Kundera", + "Charles Dickens", + "J.R.R. Tolkien", + "Douglas Adams"); + + List actual = tested.processNestedReaderDataFromReaderList(); + assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); + } +} \ No newline at end of file diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java deleted file mode 100644 index 151554efde..0000000000 --- a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/UserConsumerServiceImplUnitTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.baeldung.webclient.json; - -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; - -import java.util.Arrays; -import java.util.List; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; - -public class UserConsumerServiceImplUnitTest { - - private static String USER_JSON = "[{\"id\":1,\"name\":\"user1\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user1_address1_postCode\"}," + - "{\"addressLine1\":\"address2_addressLine1\",\"addressLine2\":\"address2_addressLine2\",\"town\":\"address2_town\",\"postCode\":\"user1_address2_postCode\"}]}," + - "{\"id\":2,\"name\":\"user2\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user2_address1_postCode\"}]}]"; - - private static String BASE_URL = "http://localhost:8080"; - - WebClient webClientMock = WebClient.builder() - .exchangeFunction(clientRequest -> Mono.just(ClientResponse.create(HttpStatus.OK) - .header("content-type", "application/json") - .body(USER_JSON) - .build())) - .build(); - - private final UserConsumerService tested = new UserConsumerServiceImpl(webClientMock); - - @Test - void when_processUserDataFromObjectArray_then_OK() { - List expected = Arrays.asList("user1", "user2"); - List actual = tested.processUserDataFromObjectArray(); - assertThat(actual, contains(expected.get(0), expected.get(1))); - } - - @Test - void when_processUserDataFromUserArray_then_OK() { - List expected = Arrays.asList("user1", "user2"); - List actual = tested.processUserDataFromUserArray(); - assertThat(actual, contains(expected.get(0), expected.get(1))); - } - - @Test - void when_processUserDataFromUserList_then_OK() { - List expected = Arrays.asList("user1", "user2"); - List actual = tested.processUserDataFromUserList(); - assertThat(actual, contains(expected.get(0), expected.get(1))); - } - - @Test - void when_processNestedUserDataFromUserArray_then_OK() { - List expected = Arrays.asList( - "user1_address1_postCode", - "user1_address2_postCode", - "user2_address1_postCode"); - - List actual = tested.processNestedUserDataFromUserArray(); - assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2))); - } - - @Test - void when_processNestedUserDataFromUserList_then_OK() { - List expected = Arrays.asList( - "user1_address1_postCode", - "user1_address2_postCode", - "user2_address1_postCode"); - - List actual = tested.processNestedUserDataFromUserList(); - assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2))); - } -} \ No newline at end of file From a0425afd1b8710216221e0c16ba4a473f1cac373 Mon Sep 17 00:00:00 2001 From: Trixi Turny Date: Sat, 23 Jan 2021 11:25:11 +0000 Subject: [PATCH 3/4] MASH-4748 fix Reader object and url with WebClient --- .../baeldung/webclient/json/model/Reader.java | 30 +++++++++++++++++++ .../ReaderConsumerServiceImplUnitTest.java | 4 +-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java index e69de29bb2..9fc480c3df 100644 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java @@ -0,0 +1,30 @@ +package com.baeldung.webclient.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Reader { + private final int id; + private final String name; + private final List favouriteBooks; + + @JsonCreator + public Reader( + @JsonProperty("id") int id, + @JsonProperty("name") String name, + @JsonProperty("favouriteBooks") List favoriteBooks) { + this.id = id; + this.name = name; + this.favouriteBooks = favoriteBooks; + } + + public String getName() { + return name; + } + + public List getFavouriteBooks() { return favouriteBooks; } +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java index 92f7bf4f3f..065f1dc11a 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java @@ -19,9 +19,9 @@ public class ReaderConsumerServiceImplUnitTest { "{\"id\":2,\"name\":\"reader2\",\"favouriteBooks\":[{\"author\":\"J.R.R. Tolkien\",\"title\":\"Lord of the Rings\"}, " + "{\"author\":\"Douglas Adams\",\"title\":\"The Hitchhiker\'s Guide to the Galaxy\"}]}]"; - private static String BASE_URL = "http://localhost:8080"; + private static String BASE_URL = "http://localhost:8080/readers"; - WebClient webClientMock = WebClient.builder() + WebClient webClientMock = WebClient.builder().baseUrl(BASE_URL) .exchangeFunction(clientRequest -> Mono.just(ClientResponse.create(HttpStatus.OK) .header("content-type", "application/json") .body(READER_JSON) From c3741487d89705dc28eac515330d9e4adb301c1f Mon Sep 17 00:00:00 2001 From: Trixi Turny Date: Sat, 23 Jan 2021 12:56:18 +0000 Subject: [PATCH 4/4] BAEL-4748 update examples with favouriteBook --- .../webclient/json/ReaderConsumerService.java | 8 ++-- .../json/ReaderConsumerServiceImpl.java | 16 ++++---- .../baeldung/webclient/json/model/Reader.java | 15 ++++--- .../ReaderConsumerServiceImplUnitTest.java | 41 ++++++++++++------- 4 files changed, 48 insertions(+), 32 deletions(-) diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java index b0bc71d2ed..17676b3f33 100644 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java @@ -1,14 +1,16 @@ package com.baeldung.webclient.json; +import com.baeldung.webclient.json.model.Book; + import java.util.List; public interface ReaderConsumerService { - List processReaderDataFromObjectArray(); + List processReaderDataFromObjectArray(); - List processReaderDataFromReaderArray(); + List processReaderDataFromReaderArray(); - List processReaderDataFromReaderList(); + List processReaderDataFromReaderList(); List processNestedReaderDataFromReaderArray(); diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java index d1800a7f65..8f1a4c019a 100644 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java @@ -21,7 +21,7 @@ public class ReaderConsumerServiceImpl implements ReaderConsumerService { this.webClient = webClient; } @Override - public List processReaderDataFromObjectArray() { + public List processReaderDataFromObjectArray() { Mono response = webClient.get() .accept(MediaType.APPLICATION_JSON) .retrieve() @@ -29,12 +29,12 @@ public class ReaderConsumerServiceImpl implements ReaderConsumerService { Object[] objects = response.block(); return Arrays.stream(objects) .map(object -> mapper.convertValue(object, Reader.class)) - .map(Reader::getName) + .map(Reader::getFavouriteBook) .collect(Collectors.toList()); } @Override - public List processReaderDataFromReaderArray() { + public List processReaderDataFromReaderArray() { Mono response = webClient.get() .accept(MediaType.APPLICATION_JSON) @@ -43,12 +43,12 @@ public class ReaderConsumerServiceImpl implements ReaderConsumerService { Reader[] readers = response.block(); return Arrays.stream(readers) - .map(Reader::getName) + .map(Reader::getFavouriteBook) .collect(Collectors.toList()); } @Override - public List processReaderDataFromReaderList() { + public List processReaderDataFromReaderList() { Mono> response = webClient.get() .accept(MediaType.APPLICATION_JSON) .retrieve() @@ -56,7 +56,7 @@ public class ReaderConsumerServiceImpl implements ReaderConsumerService { List readers = response.block(); return readers.stream() - .map(Reader::getName) + .map(Reader::getFavouriteBook) .collect(Collectors.toList()); } @@ -69,7 +69,7 @@ public class ReaderConsumerServiceImpl implements ReaderConsumerService { Reader[] readers = response.block(); return Arrays.stream(readers) - .flatMap(reader -> reader.getFavouriteBooks().stream()) + .flatMap(reader -> reader.getBooksRead().stream()) .map(Book::getAuthor) .collect(Collectors.toList()); } @@ -83,7 +83,7 @@ public class ReaderConsumerServiceImpl implements ReaderConsumerService { List readers = response.block(); return readers.stream() - .flatMap(reader -> reader.getFavouriteBooks().stream()) + .flatMap(reader -> reader.getBooksRead().stream()) .map(Book::getAuthor) .collect(Collectors.toList()); } diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java index 9fc480c3df..7d02853ea1 100644 --- a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java @@ -10,21 +10,24 @@ import java.util.List; public class Reader { private final int id; private final String name; - private final List favouriteBooks; + private final Book favouriteBook; + private final List booksRead; @JsonCreator public Reader( @JsonProperty("id") int id, @JsonProperty("name") String name, - @JsonProperty("favouriteBooks") List favoriteBooks) { + @JsonProperty("favouriteBook") Book favouriteBook, + @JsonProperty("booksRead") List booksRead) { this.id = id; this.name = name; - this.favouriteBooks = favoriteBooks; + this.favouriteBook = favouriteBook; + this.booksRead =booksRead; } - public String getName() { - return name; + public Book getFavouriteBook() { + return favouriteBook; } - public List getFavouriteBooks() { return favouriteBooks; } + public List getBooksRead() { return booksRead; } } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java index 065f1dc11a..51f0a5c1bb 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java @@ -1,5 +1,6 @@ package com.baeldung.webclient.json; +import com.baeldung.webclient.json.model.Book; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.web.reactive.function.client.ClientResponse; @@ -10,13 +11,16 @@ import java.util.Arrays; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.hasProperty; public class ReaderConsumerServiceImplUnitTest { - private static String READER_JSON = "[{\"id\":1,\"name\":\"reader1\",\"favouriteBooks\":[{\"author\":\"Milan Kundera\",\"title\":\"The Unbearable Lightness of Being\"}," + - "{\"author\":\"Charles Dickens\",\"title\":\"Oliver Twist\"}]}," + - "{\"id\":2,\"name\":\"reader2\",\"favouriteBooks\":[{\"author\":\"J.R.R. Tolkien\",\"title\":\"Lord of the Rings\"}, " + + private static String READER_JSON = "[{\"id\":1,\"name\":\"reader1\",\"favouriteBook\":{\"author\":\"Milan Kundera\",\"title\":\"The Unbearable Lightness of Being\"}," + + "\"booksRead\":[{\"author\":\"Charles Dickens\",\"title\":\"Oliver Twist\"},{\"author\":\"Milan Kundera\",\"title\":\"The Unbearable Lightness of Being\"}]}," + + "{\"id\":2,\"name\":\"reader2\",\"favouriteBook\":{\"author\":\"Douglas Adams\",\"title\":\"The Hitchhiker\'s Guide to the Galaxy\"}," + + "\"booksRead\":[{\"author\":\"J.R.R. Tolkien\",\"title\":\"Lord of the Rings\"}, " + "{\"author\":\"Douglas Adams\",\"title\":\"The Hitchhiker\'s Guide to the Galaxy\"}]}]"; private static String BASE_URL = "http://localhost:8080/readers"; @@ -32,23 +36,30 @@ public class ReaderConsumerServiceImplUnitTest { @Test void when_processReaderDataFromObjectArray_then_OK() { - List expected = Arrays.asList("reader1", "reader2"); - List actual = tested.processReaderDataFromObjectArray(); - assertThat(actual, contains(expected.get(0), expected.get(1))); + String expectedAuthor1 = "Milan Kundera"; + String expectedAuthor2 = "Douglas Adams"; + List actual = tested.processReaderDataFromObjectArray(); + assertThat(actual, hasItems(hasProperty("author", is(expectedAuthor1)), + hasProperty("author", is(expectedAuthor2)))); } @Test void when_processReaderDataFromReaderArray_then_OK() { - List expected = Arrays.asList("reader1", "reader2"); - List actual = tested.processReaderDataFromReaderArray(); - assertThat(actual, contains(expected.get(0), expected.get(1))); + String expectedAuthor1 = "Milan Kundera"; + String expectedAuthor2 = "Douglas Adams"; + List actual = tested.processReaderDataFromReaderArray(); + assertThat(actual, hasItems(hasProperty("author", is(expectedAuthor1)), + hasProperty("author", is(expectedAuthor2)))); } @Test void when_processReaderDataFromReaderList_then_OK() { - List expected = Arrays.asList("reader1", "reader2"); - List actual = tested.processReaderDataFromReaderList(); - assertThat(actual, contains(expected.get(0), expected.get(1))); + String expectedAuthor1 = "Milan Kundera"; + String expectedAuthor2 = "Douglas Adams"; + List actual = tested.processReaderDataFromReaderList(); + assertThat(actual, hasItems(hasProperty("author", is(expectedAuthor1)), + hasProperty("author", is(expectedAuthor2)))); + } @Test @@ -60,7 +71,7 @@ public class ReaderConsumerServiceImplUnitTest { "Douglas Adams"); List actual = tested.processNestedReaderDataFromReaderArray(); - assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); + assertThat(actual, hasItems(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); } @Test @@ -72,6 +83,6 @@ public class ReaderConsumerServiceImplUnitTest { "Douglas Adams"); List actual = tested.processNestedReaderDataFromReaderList(); - assertThat(actual, contains(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); + assertThat(actual, hasItems(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); } } \ No newline at end of file