From a58783707caf2a8b3c1d27f13393724c92a8b69d Mon Sep 17 00:00:00 2001 From: ovidiu-mihai98 <138307181+ovidiumihaitacu@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:50:18 +0200 Subject: [PATCH] [BAEL-7067] Difference Between Entity and DTO --- .../entitydtodifferences/Application.java | 12 +++ .../controller/UserController.java | 39 ++++++++ .../entitydtodifferences/dto/BookDto.java | 30 ++++++ .../dto/UserCreationDto.java | 48 ++++++++++ .../dto/UserResponseDto.java | 48 ++++++++++ .../entitydtodifferences/entity/Book.java | 39 ++++++++ .../entitydtodifferences/entity/User.java | 90 ++++++++++++++++++ .../mapper/UserMapper.java | 34 +++++++ .../repository/UserRepository.java | 11 +++ .../ApplicationIntegrationTest.java | 15 +++ .../UserControllerIntegrationTest.java | 93 +++++++++++++++++++ .../entity/BookUnitTest.java | 19 ++++ .../entity/UserUnitTest.java | 51 ++++++++++ .../mapper/UserMapperUnitTest.java | 87 +++++++++++++++++ 14 files changed, 616 insertions(+) create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/Application.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/controller/UserController.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/BookDto.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserCreationDto.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserResponseDto.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/Book.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/User.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/mapper/UserMapper.java create mode 100644 spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/repository/UserRepository.java create mode 100644 spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/ApplicationIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/controller/UserControllerIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/BookUnitTest.java create mode 100644 spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/UserUnitTest.java create mode 100644 spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/mapper/UserMapperUnitTest.java diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/Application.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/Application.java new file mode 100644 index 0000000000..4a780ac17a --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.entitydtodifferences; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/controller/UserController.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/controller/UserController.java new file mode 100644 index 0000000000..66cecacd9b --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/controller/UserController.java @@ -0,0 +1,39 @@ +package com.baeldung.entitydtodifferences.controller; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.entitydtodifferences.dto.UserCreationDto; +import com.baeldung.entitydtodifferences.dto.UserResponseDto; +import com.baeldung.entitydtodifferences.mapper.UserMapper; +import com.baeldung.entitydtodifferences.repository.UserRepository; + +@RestController +@RequestMapping("/users") +public class UserController { + + private final UserRepository userRepository; + + public UserController(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @GetMapping + public List getUsers() { + return userRepository.findAll() + .stream() + .map(UserMapper::toDto) + .collect(Collectors.toList()); + } + + @PostMapping + public UserResponseDto createUser(@RequestBody UserCreationDto userCreationDto) { + return UserMapper.toDto(userRepository.save(UserMapper.toEntity(userCreationDto))); + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/BookDto.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/BookDto.java new file mode 100644 index 0000000000..a5ee25f105 --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/BookDto.java @@ -0,0 +1,30 @@ +package com.baeldung.entitydtodifferences.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class BookDto { + + @JsonProperty("NAME") + private final String name; + + @JsonProperty("AUTHOR") + private final String author; + + // Default constructor for Jackson deserialization + public BookDto() { + this(null, null); + } + + public BookDto(String name, String author) { + this.name = name; + this.author = author; + } + + public String getName() { + return name; + } + + public String getAuthor() { + return author; + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserCreationDto.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserCreationDto.java new file mode 100644 index 0000000000..0859c042cf --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserCreationDto.java @@ -0,0 +1,48 @@ +package com.baeldung.entitydtodifferences.dto; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class UserCreationDto { + + @JsonProperty("FIRST_NAME") + private final String firstName; + + @JsonProperty("LAST_NAME") + private final String lastName; + + @JsonProperty("ADDRESS") + private final String address; + + @JsonProperty("BOOKS") + private final List books; + + // Default constructor for Jackson deserialization + public UserCreationDto() { + this(null, null, null, null); + } + + public UserCreationDto(String firstName, String lastName, String address, List books) { + this.firstName = firstName; + this.lastName = lastName; + this.address = address; + this.books = books; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getAddress() { + return address; + } + + public List getBooks() { + return books; + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserResponseDto.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserResponseDto.java new file mode 100644 index 0000000000..910689dd41 --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/dto/UserResponseDto.java @@ -0,0 +1,48 @@ +package com.baeldung.entitydtodifferences.dto; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class UserResponseDto { + + @JsonProperty("ID") + private final Long id; + + @JsonProperty("FIRST_NAME") + private final String firstName; + + @JsonProperty("LAST_NAME") + private final String lastName; + + @JsonProperty("BOOKS") + private final List books; + + // Default constructor for Jackson deserialization + public UserResponseDto() { + this(null, null, null, null); + } + + public UserResponseDto(Long id, String firstName, String lastName, List books) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.books = books; + } + + public Long getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public List getBooks() { + return books; + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/Book.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/Book.java new file mode 100644 index 0000000000..88e895467a --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/Book.java @@ -0,0 +1,39 @@ +package com.baeldung.entitydtodifferences.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "books") +public class Book { + + @Id + private String name; + private String author; + + // Default constructor for JPA deserialization + public Book() { + } + + public Book(String name, String author) { + this.name = name; + this.author = author; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/User.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/User.java new file mode 100644 index 0000000000..6a404e9f1f --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/entity/User.java @@ -0,0 +1,90 @@ +package com.baeldung.entitydtodifferences.entity; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String firstName; + private String lastName; + private String address; + + @OneToMany(cascade = CascadeType.ALL) + private List books; + + // Default constructor for JPA deserialization + public User() { + } + + public User(String firstName, String lastName, String address, List books) { + this.firstName = firstName; + this.lastName = lastName; + this.address = address; + this.books = books; + } + + public String getNameOfMostOwnedBook() { + Map bookOwnershipCount = books.stream() + .collect(Collectors.groupingBy(Book::getName, Collectors.counting())); + return bookOwnershipCount.entrySet() + .stream() + .max(Map.Entry.comparingByValue()) + .map(Map.Entry::getKey) + .orElse(null); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/mapper/UserMapper.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/mapper/UserMapper.java new file mode 100644 index 0000000000..0c6899f98b --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/mapper/UserMapper.java @@ -0,0 +1,34 @@ +package com.baeldung.entitydtodifferences.mapper; + +import java.util.stream.Collectors; + +import com.baeldung.entitydtodifferences.dto.BookDto; +import com.baeldung.entitydtodifferences.dto.UserCreationDto; +import com.baeldung.entitydtodifferences.dto.UserResponseDto; +import com.baeldung.entitydtodifferences.entity.Book; +import com.baeldung.entitydtodifferences.entity.User; + +public class UserMapper { + + public static UserResponseDto toDto(User entity) { + return new UserResponseDto(entity.getId(), entity.getFirstName(), entity.getLastName(), entity.getBooks() + .stream() + .map(UserMapper::toDto) + .collect(Collectors.toList())); + } + + public static User toEntity(UserCreationDto dto) { + return new User(dto.getFirstName(), dto.getLastName(), dto.getAddress(), dto.getBooks() + .stream() + .map(UserMapper::toEntity) + .collect(Collectors.toList())); + } + + public static BookDto toDto(Book entity) { + return new BookDto(entity.getName(), entity.getAuthor()); + } + + public static Book toEntity(BookDto dto) { + return new Book(dto.getName(), dto.getAuthor()); + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/repository/UserRepository.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/repository/UserRepository.java new file mode 100644 index 0000000000..4529de698e --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/entitydtodifferences/repository/UserRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.entitydtodifferences.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.baeldung.entitydtodifferences.entity.User; + +@Repository +public interface UserRepository extends JpaRepository { + +} diff --git a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/ApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/ApplicationIntegrationTest.java new file mode 100644 index 0000000000..839bb381ec --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/ApplicationIntegrationTest.java @@ -0,0 +1,15 @@ +package com.baeldung.entitydtodifferences; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ApplicationIntegrationTest { + + @Test + public void contextLoads() { + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/controller/UserControllerIntegrationTest.java b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/controller/UserControllerIntegrationTest.java new file mode 100644 index 0000000000..83e359e378 --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/controller/UserControllerIntegrationTest.java @@ -0,0 +1,93 @@ +package com.baeldung.entitydtodifferences.controller; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import com.baeldung.entitydtodifferences.entity.Book; +import com.baeldung.entitydtodifferences.entity.User; +import com.baeldung.entitydtodifferences.repository.UserRepository; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@AutoConfigureMockMvc +public class UserControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ObjectMapper objectMapper; + + @BeforeEach + public void beforeEach() { + userRepository.deleteAll(); + } + + @Test + public void givenUsersAreExisting_whenGetUsers_thenUsersAreReturned() throws Exception { + //given + Book book1 = new Book("Book1", "Author1"); + Book book2 = new Book("Book2", "Author2"); + User savedUser = userRepository.save(new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2))); + String expectedJson = String.format( + "[{\"ID\":%s,\"FIRST_NAME\":\"John\",\"LAST_NAME\":\"Doe\",\"BOOKS\":[{\"NAME\":\"Book1\",\"AUTHOR\":\"Author1\"},{\"NAME\":\"Book2\",\"AUTHOR\":\"Author2\"}]}]", + savedUser.getId()); + //when + MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/users") + .contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + //then + assertEquals(expectedJson, result.getResponse() + .getContentAsString()); + } + + @Test + public void givenValidUser_whenPostUser_thenUserIsCreated() throws Exception { + //given + String user = "{\"FIRST_NAME\":\"John\",\"LAST_NAME\":\"Doe\",\"BOOKS\":[{\"NAME\":\"Book1\",\"AUTHOR\":\"Author1\"},{\"NAME\":\"Book2\",\"AUTHOR\":\"Author2\"}]}"; + //when + MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/users") + .content(user) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andReturn(); + JsonNode responseJson = objectMapper.readTree(result.getResponse() + .getContentAsString()); + //then + assertEquals("John", responseJson.get("FIRST_NAME") + .asText()); + assertEquals("Doe", responseJson.get("LAST_NAME") + .asText()); + assertTrue(responseJson.has("BOOKS")); + JsonNode booksArray = responseJson.get("BOOKS"); + assertEquals(2, booksArray.size()); + assertEquals("Book1", booksArray.get(0) + .get("NAME") + .asText()); + assertEquals("Author1", booksArray.get(0) + .get("AUTHOR") + .asText()); + assertEquals("Book2", booksArray.get(1) + .get("NAME") + .asText()); + assertEquals("Author2", booksArray.get(1) + .get("AUTHOR") + .asText()); + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/BookUnitTest.java b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/BookUnitTest.java new file mode 100644 index 0000000000..60e229b7c9 --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/BookUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung.entitydtodifferences.entity; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.Test; + +public class BookUnitTest { + + @Test + public void whenBookInitialized_thenInitializedCorrectly() { + //when + Book book = new Book("Book1", "Author1"); + //then + assertNotNull(book); + assertEquals("Book1", book.getName()); + assertEquals("Author1", book.getAuthor()); + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/UserUnitTest.java b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/UserUnitTest.java new file mode 100644 index 0000000000..0d1efe7129 --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/entity/UserUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.entitydtodifferences.entity; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Test; + +public class UserUnitTest { + + @Test + public void whenUserInitialized_thenInitializedCorrectly() { + //when + Book book1 = new Book("Book1", "Author1"); + Book book2 = new Book("Book2", "Author2"); + User user = new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2)); + //then + assertNotNull(user); + assertEquals("John", user.getFirstName()); + assertEquals("Doe", user.getLastName()); + assertEquals("123 Main St", user.getAddress()); + assertEquals(2, user.getBooks() + .size()); + } + + @Test + public void givenUserOwningMultipleBooks_whenGetNameOfMostOwnedBook_thenComputedCorrectly() { + //given + Book book1 = new Book("Book1", "Author1"); + Book book2 = new Book("Book2", "Author2"); + Book book3 = new Book("Book2", "Author3"); + User user = new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2, book3)); + //when + String mostOwnedBook = user.getNameOfMostOwnedBook(); + //then + assertEquals("Book2", mostOwnedBook); + } + + @Test + public void givenUserWithNoBooks_henGetNameOfMostOwnedBook_thenReturnedNull() { + //given + User user = new User("John", "Doe", "123 Main St", Collections.emptyList()); + //when + String mostOwnedBook = user.getNameOfMostOwnedBook(); + //then + assertNull(mostOwnedBook); + } +} diff --git a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/mapper/UserMapperUnitTest.java b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/mapper/UserMapperUnitTest.java new file mode 100644 index 0000000000..5154898877 --- /dev/null +++ b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/entitydtodifferences/mapper/UserMapperUnitTest.java @@ -0,0 +1,87 @@ +package com.baeldung.entitydtodifferences.mapper; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +import com.baeldung.entitydtodifferences.dto.BookDto; +import com.baeldung.entitydtodifferences.dto.UserCreationDto; +import com.baeldung.entitydtodifferences.dto.UserResponseDto; +import com.baeldung.entitydtodifferences.entity.Book; +import com.baeldung.entitydtodifferences.entity.User; + +public class UserMapperUnitTest { + + @Test + public void givenUserEntity_whenMappedToDto_thenMappedCorrectly() { + //given + Book book1 = new Book("Book1", "Author1"); + Book book2 = new Book("Book2", "Author2"); + User user = new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2)); + //when + UserResponseDto userDto = UserMapper.toDto(user); + //then + assertEquals(user.getId(), userDto.getId()); + assertEquals(user.getFirstName(), userDto.getFirstName()); + assertEquals(user.getLastName(), userDto.getLastName()); + List bookDtos = userDto.getBooks(); + assertEquals(2, bookDtos.size()); + assertEquals(book1.getName(), bookDtos.get(0) + .getName()); + assertEquals(book1.getAuthor(), bookDtos.get(0) + .getAuthor()); + assertEquals(book2.getName(), bookDtos.get(1) + .getName()); + assertEquals(book2.getAuthor(), bookDtos.get(1) + .getAuthor()); + } + + @Test + public void givenUserDto_whenMappedToEntity_thenMappedCorrectly() { + //given + BookDto bookDto1 = new BookDto("Book3", "Author3"); + BookDto bookDto2 = new BookDto("Book4", "Author4"); + UserCreationDto userDto = new UserCreationDto("Jane", "Doe", "456 Oak St", Arrays.asList(bookDto1, bookDto2)); + //when + User user = UserMapper.toEntity(userDto); + //then + assertEquals(user.getFirstName(), userDto.getFirstName()); + assertEquals(user.getLastName(), userDto.getLastName()); + assertEquals(user.getAddress(), userDto.getAddress()); + List books = user.getBooks(); + assertEquals(2, books.size()); + assertEquals(bookDto1.getName(), books.get(0) + .getName()); + assertEquals(bookDto1.getAuthor(), books.get(0) + .getAuthor()); + assertEquals(bookDto2.getName(), books.get(1) + .getName()); + assertEquals(bookDto2.getAuthor(), books.get(1) + .getAuthor()); + } + + @Test + public void givenBookEntity_whenMappedToDto_thenMappedCorrectly() { + //given + Book book = new Book("Book5", "Author5"); + //when + BookDto bookDto = UserMapper.toDto(book); + //then + assertEquals(book.getName(), bookDto.getName()); + assertEquals(book.getAuthor(), bookDto.getAuthor()); + } + + @Test + public void givenBookDto_whenMappedToEntity_thenMappedCorrectly() { + //given + BookDto bookDto = new BookDto("Book6", "Author6"); + //when + Book book = UserMapper.toEntity(bookDto); + //then + assertEquals(bookDto.getName(), book.getName()); + assertEquals(bookDto.getAuthor(), book.getAuthor()); + } +}