diff --git a/src/main/java/toy/bookchat/bookchat/domain/book/service/BookReader.java b/src/main/java/toy/bookchat/bookchat/domain/book/service/BookReader.java new file mode 100644 index 00000000..448e1cc7 --- /dev/null +++ b/src/main/java/toy/bookchat/bookchat/domain/book/service/BookReader.java @@ -0,0 +1,21 @@ +package toy.bookchat.bookchat.domain.book.service; + +import java.time.LocalDate; +import org.springframework.stereotype.Component; +import toy.bookchat.bookchat.domain.book.Book; +import toy.bookchat.bookchat.domain.book.repository.BookRepository; + +@Component +public class BookReader { + + private final BookRepository bookRepository; + + public BookReader(BookRepository bookRepository) { + this.bookRepository = bookRepository; + } + + public Book readBook(String isbn, LocalDate publishAt, Book book) { + return bookRepository.findByIsbnAndPublishAt(isbn, publishAt) + .orElseGet(() -> bookRepository.save(book)); + } +} diff --git a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManager.java b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManager.java index 0fc80c25..9128fbce 100644 --- a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManager.java +++ b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManager.java @@ -2,17 +2,27 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import toy.bookchat.bookchat.domain.agony.repository.AgonyRecordRepository; +import toy.bookchat.bookchat.domain.agony.repository.AgonyRepository; import toy.bookchat.bookchat.domain.bookshelf.BookReport; import toy.bookchat.bookchat.domain.bookshelf.BookShelf; import toy.bookchat.bookchat.domain.bookshelf.repository.BookReportRepository; +import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository; @Component public class BookShelfManager { + private final BookShelfRepository bookShelfRepository; private final BookReportRepository bookReportRepository; + private final AgonyRepository agonyRepository; + private final AgonyRecordRepository agonyRecordRepository; - public BookShelfManager(BookReportRepository bookReportRepository) { + + public BookShelfManager(BookReportRepository bookReportRepository, BookShelfRepository bookShelfRepository, AgonyRepository agonyRepository, AgonyRecordRepository agonyRecordRepository) { this.bookReportRepository = bookReportRepository; + this.bookShelfRepository = bookShelfRepository; + this.agonyRepository = agonyRepository; + this.agonyRecordRepository = agonyRecordRepository; } @Transactional @@ -20,4 +30,18 @@ public void append(BookShelf bookShelf, BookReport bookReport) { bookReportRepository.save(bookReport); bookShelf.writeReportInStateOfCompleteReading(bookReport); } + + public void store(BookShelf bookShelf) { + bookShelfRepository.save(bookShelf); + } + + public void vacate(Long bookShelfId, Long userId) { + agonyRecordRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId); + agonyRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId); + bookShelfRepository.deleteBookShelfByIdAndUserId(bookShelfId, userId); + } + + public void remove(Long userId) { + bookShelfRepository.deleteAllByUserId(userId); + } } diff --git a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReader.java b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReader.java index 9b0b041a..4f52d20a 100644 --- a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReader.java +++ b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReader.java @@ -1,8 +1,12 @@ package toy.bookchat.bookchat.domain.bookshelf.service; +import java.time.LocalDate; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import toy.bookchat.bookchat.domain.bookshelf.BookShelf; +import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus; import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository; import toy.bookchat.bookchat.exception.notfound.book.BookNotFoundException; @@ -20,4 +24,14 @@ public BookShelf readBookShelf(Long bookShelfId, Long userId) { return bookShelfRepository.findByIdAndUserId(bookShelfId, userId) .orElseThrow(BookNotFoundException::new); } + + + public Page readBookShelf(Long userId, ReadingStatus readingStatus, Pageable pageable) { + return bookShelfRepository.findSpecificStatusBookByUserId(readingStatus, pageable, userId); + } + + public BookShelf readBookShelf(Long userId, String isbn, LocalDate publishAt) { + return bookShelfRepository.findByUserIdAndIsbnAndPublishAt(userId, isbn, publishAt) + .orElseThrow(BookNotFoundException::new); + } } diff --git a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfService.java b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfService.java index 7a147043..c9b43488 100644 --- a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfService.java +++ b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfService.java @@ -5,108 +5,64 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import toy.bookchat.bookchat.domain.agony.repository.AgonyRecordRepository; -import toy.bookchat.bookchat.domain.agony.repository.AgonyRepository; import toy.bookchat.bookchat.domain.book.Book; -import toy.bookchat.bookchat.domain.book.repository.BookRepository; +import toy.bookchat.bookchat.domain.book.service.BookReader; import toy.bookchat.bookchat.domain.bookshelf.BookShelf; import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus; -import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository; import toy.bookchat.bookchat.domain.bookshelf.service.dto.request.BookShelfRequest; import toy.bookchat.bookchat.domain.bookshelf.service.dto.request.ReviseBookShelfRequest; import toy.bookchat.bookchat.domain.bookshelf.service.dto.response.ExistenceBookOnBookShelfResponse; import toy.bookchat.bookchat.domain.bookshelf.service.dto.response.SearchBookShelfByReadingStatus; import toy.bookchat.bookchat.domain.user.User; -import toy.bookchat.bookchat.domain.user.repository.UserRepository; -import toy.bookchat.bookchat.exception.notfound.book.BookNotFoundException; -import toy.bookchat.bookchat.exception.notfound.user.UserNotFoundException; +import toy.bookchat.bookchat.domain.user.service.UserReader; @Service +@Transactional(readOnly = true) public class BookShelfService { - private final BookShelfRepository bookShelfRepository; - private final AgonyRepository agonyRepository; - private final AgonyRecordRepository agonyRecordRepository; - private final BookRepository bookRepository; - private final UserRepository userRepository; + private final BookShelfManager bookShelfManager; + private final BookShelfReader bookShelfReader; + private final BookReader bookReader; + private final UserReader userReader; - public BookShelfService(BookShelfRepository bookShelfRepository, - AgonyRepository agonyRepository, AgonyRecordRepository agonyRecordRepository, - BookRepository bookRepository, - UserRepository userRepository) { - this.bookShelfRepository = bookShelfRepository; - this.agonyRepository = agonyRepository; - this.agonyRecordRepository = agonyRecordRepository; - this.bookRepository = bookRepository; - this.userRepository = userRepository; + public BookShelfService(UserReader userReader, BookShelfManager bookShelfManager, BookShelfReader bookShelfReader, BookReader bookReader) { + this.userReader = userReader; + this.bookShelfManager = bookShelfManager; + this.bookShelfReader = bookShelfReader; + this.bookReader = bookReader; } @Transactional public void putBookOnBookShelf(BookShelfRequest bookShelfRequest, Long userId) { - Book book = bookRepository.findByIsbnAndPublishAt(bookShelfRequest.getIsbn(), - bookShelfRequest.getPublishAt()) - .orElseGet(() -> bookRepository.save(bookShelfRequest.extractBookEntity())); - User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - - bookShelfRepository.save(createBookShelfByReadingStatus(bookShelfRequest, book, user)); - } - - private BookShelf createBookShelfByReadingStatus(BookShelfRequest bookShelfRequest, - Book book, User user) { - if (bookShelfRequest.isCompleteReading()) { - return BookShelf.builder() - .book(book) - .readingStatus(bookShelfRequest.getReadingStatus()) - .user(user) - .star(bookShelfRequest.getStar()) - .build(); - } - return BookShelf.builder() - .book(book) - .readingStatus(bookShelfRequest.getReadingStatus()) - .user(user) - .build(); + Book book = bookReader.readBook(bookShelfRequest.getIsbn(), bookShelfRequest.getPublishAt(), bookShelfRequest.extractBookEntity()); + User user = userReader.readUser(userId); + bookShelfManager.store(bookShelfRequest.createBookShelfByReadingStatus(book, user)); } - @Transactional(readOnly = true) - public SearchBookShelfByReadingStatus takeBooksOutOfBookShelves(ReadingStatus readingStatus, - Pageable pageable, Long userId) { - Page pagingBookShelves = bookShelfRepository.findSpecificStatusBookByUserId( - readingStatus, pageable, - userId); - + public SearchBookShelfByReadingStatus takeBooksOutOfBookShelves(ReadingStatus readingStatus, Pageable pageable, Long userId) { + Page pagingBookShelves = bookShelfReader.readBookShelf(userId, readingStatus, pageable); return new SearchBookShelfByReadingStatus(pagingBookShelves); } - @Transactional(readOnly = true) - public ExistenceBookOnBookShelfResponse getBookIfExisted(String isbn, - LocalDate publishAt, Long userId) { - BookShelf bookShelf = bookShelfRepository.findByUserIdAndIsbnAndPublishAt(userId, isbn, - publishAt) - .orElseThrow(BookNotFoundException::new); - + public ExistenceBookOnBookShelfResponse getBookIfExisted(String isbn, LocalDate publishAt, Long userId) { + BookShelf bookShelf = bookShelfReader.readBookShelf(userId, isbn, publishAt); return ExistenceBookOnBookShelfResponse.from(bookShelf); } @Transactional - public void reviseBookShelf(Long bookShelfId, ReviseBookShelfRequest reviseBookShelfRequest, - Long userId) { - BookShelf bookShelf = bookShelfRepository.findByIdAndUserId(bookShelfId, userId) - .orElseThrow(BookNotFoundException::new); - + public void reviseBookShelf(Long bookShelfId, ReviseBookShelfRequest reviseBookShelfRequest, Long userId) { + BookShelf bookShelf = bookShelfReader.readBookShelf(bookShelfId, userId); reviseBookShelfRequest.applyChanges(bookShelf); } @Transactional public void deleteBookShelf(Long bookShelfId, Long userId) { - agonyRecordRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId); - agonyRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId); - bookShelfRepository.deleteBookShelfByIdAndUserId(bookShelfId, userId); + bookShelfManager.vacate(bookShelfId, userId); } @Transactional public void deleteAllUserBookShelves(Long userId) { - bookShelfRepository.deleteAllByUserId(userId); + bookShelfManager.remove(userId); } } diff --git a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/request/BookShelfRequest.java b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/request/BookShelfRequest.java index 289ade10..082719ba 100644 --- a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/request/BookShelfRequest.java +++ b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/request/BookShelfRequest.java @@ -11,8 +11,10 @@ import lombok.Getter; import lombok.NoArgsConstructor; import toy.bookchat.bookchat.domain.book.Book; +import toy.bookchat.bookchat.domain.bookshelf.BookShelf; import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus; import toy.bookchat.bookchat.domain.bookshelf.Star; +import toy.bookchat.bookchat.domain.user.User; @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -61,4 +63,20 @@ public String getIsbn() { public LocalDate getPublishAt() { return this.bookRequest.getPublishAt(); } + + public BookShelf createBookShelfByReadingStatus(Book book, User user) { + if (this.isCompleteReading()) { + return BookShelf.builder() + .book(book) + .readingStatus(this.getReadingStatus()) + .user(user) + .star(this.getStar()) + .build(); + } + return BookShelf.builder() + .book(book) + .readingStatus(this.getReadingStatus()) + .user(user) + .build(); + } } diff --git a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/response/ExistenceBookOnBookShelfResponse.java b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/response/ExistenceBookOnBookShelfResponse.java index ccfd83a6..8b806806 100644 --- a/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/response/ExistenceBookOnBookShelfResponse.java +++ b/src/main/java/toy/bookchat/bookchat/domain/bookshelf/service/dto/response/ExistenceBookOnBookShelfResponse.java @@ -19,7 +19,6 @@ private ExistenceBookOnBookShelfResponse(Long bookShelfId, } public static ExistenceBookOnBookShelfResponse from(BookShelf bookShelf) { - return new ExistenceBookOnBookShelfResponse(bookShelf.getId(), - bookShelf.getReadingStatus()); + return new ExistenceBookOnBookShelfResponse(bookShelf.getId(), bookShelf.getReadingStatus()); } } diff --git a/src/main/java/toy/bookchat/bookchat/domain/user/service/UserReader.java b/src/main/java/toy/bookchat/bookchat/domain/user/service/UserReader.java new file mode 100644 index 00000000..b49ed61b --- /dev/null +++ b/src/main/java/toy/bookchat/bookchat/domain/user/service/UserReader.java @@ -0,0 +1,20 @@ +package toy.bookchat.bookchat.domain.user.service; + +import org.springframework.stereotype.Component; +import toy.bookchat.bookchat.domain.user.User; +import toy.bookchat.bookchat.domain.user.repository.UserRepository; +import toy.bookchat.bookchat.exception.notfound.user.UserNotFoundException; + +@Component +public class UserReader { + + private final UserRepository userRepository; + + public UserReader(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public User readUser(Long userId) { + return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + } +} diff --git a/src/test/java/toy/bookchat/bookchat/domain/book/service/BookReaderTest.java b/src/test/java/toy/bookchat/bookchat/domain/book/service/BookReaderTest.java new file mode 100644 index 00000000..257b818e --- /dev/null +++ b/src/test/java/toy/bookchat/bookchat/domain/book/service/BookReaderTest.java @@ -0,0 +1,42 @@ +package toy.bookchat.bookchat.domain.book.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + +import java.time.LocalDate; +import java.util.Optional; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import toy.bookchat.bookchat.domain.book.Book; +import toy.bookchat.bookchat.domain.book.repository.BookRepository; + +@ExtendWith(MockitoExtension.class) +class BookReaderTest { + + @Mock + private BookRepository bookRepository; + @InjectMocks + private BookReader bookReader; + + @Test + void isbn_출판일과_일치하는_책이있다면_조회한다() throws Exception { + Book book = Book.builder().build(); + given(bookRepository.findByIsbnAndPublishAt(any(), any())).willReturn(Optional.of(book)); + Book readBook = bookReader.readBook("G5J5X8U", LocalDate.now(), null); + + assertThat(readBook).isEqualTo(book); + } + + @Test + void isbn_출판일과_일치하는_책이없다면_신규등록후_반환한다() throws Exception { + Book book = Book.builder().build(); + given(bookRepository.save(any())).willReturn(book); + Book readBook = bookReader.readBook("G5J5X8U", LocalDate.now(), null); + + assertThat(readBook).isEqualTo(book); + } +} \ No newline at end of file diff --git a/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManagerTest.java b/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManagerTest.java index 125f8892..276e5b29 100644 --- a/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManagerTest.java +++ b/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfManagerTest.java @@ -1,6 +1,7 @@ package toy.bookchat.bookchat.domain.bookshelf.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; @@ -8,15 +9,24 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import toy.bookchat.bookchat.domain.agony.repository.AgonyRecordRepository; +import toy.bookchat.bookchat.domain.agony.repository.AgonyRepository; import toy.bookchat.bookchat.domain.bookshelf.BookReport; import toy.bookchat.bookchat.domain.bookshelf.BookShelf; import toy.bookchat.bookchat.domain.bookshelf.repository.BookReportRepository; +import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository; @ExtendWith(MockitoExtension.class) class BookShelfManagerTest { + @Mock + private BookShelfRepository bookShelfRepository; @Mock private BookReportRepository bookReportRepository; + @Mock + private AgonyRepository agonyRepository; + @Mock + private AgonyRecordRepository agonyRecordRepository; @InjectMocks private BookShelfManager bookShelfManager; @@ -33,4 +43,30 @@ class BookShelfManagerTest { assertThat(bookShelf.getBookReport()).isEqualTo(bookReport); verify(bookReportRepository).save(bookReport); } + + @Test + void 서재를_저장한다() throws Exception { + BookShelf bookShelf = BookShelf.builder() + .build(); + + bookShelfManager.store(bookShelf); + + verify(bookShelfRepository).save(bookShelf); + } + + @Test + void 서재와_관련_기록들을_비운다() throws Exception { + bookShelfManager.vacate(1L, 2L); + + verify(bookShelfRepository).deleteBookShelfByIdAndUserId(any(), any()); + verify(agonyRecordRepository).deleteByBookShelfIdAndUserId(any(), any()); + verify(agonyRepository).deleteByBookShelfIdAndUserId(any(), any()); + } + + @Test + void 사용자의_서재를_전부_삭제한다() throws Exception { + bookShelfManager.remove(1L); + + verify(bookShelfRepository).deleteAllByUserId(any()); + } } \ No newline at end of file diff --git a/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReaderTest.java b/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReaderTest.java index d4748c55..0313a93f 100644 --- a/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReaderTest.java +++ b/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfReaderTest.java @@ -1,12 +1,18 @@ package toy.bookchat.bookchat.domain.bookshelf.service; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import java.time.LocalDate; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Pageable; +import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus; import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository; import toy.bookchat.bookchat.exception.notfound.book.BookNotFoundException; @@ -19,8 +25,22 @@ class BookShelfReaderTest { private BookShelfReader bookShelfReader; @Test - void 사용자의_책장_조회시_일치하는_책장이없다면_예외_발생() throws Exception { + void 사용자id_서재id와_일치하는_서재가없다면_예외_발생() throws Exception { assertThatThrownBy(() -> bookShelfReader.readBookShelf(488L, 897L)) .isInstanceOf(BookNotFoundException.class); } + + @Test + void 사용자id_읽음상태조건과_일치하는_서재를_조회한다() throws Exception { + bookShelfReader.readBookShelf(705L, ReadingStatus.COMPLETE, mock(Pageable.class)); + + verify(bookShelfRepository).findSpecificStatusBookByUserId(any(), any(), any()); + } + + @Test + void 사용자id_isbn_발행일자와_일치하는_서재를_조회한다() throws Exception { + assertThatThrownBy(() -> { + bookShelfReader.readBookShelf(705L, "isbn", LocalDate.now()); + }).isInstanceOf(BookNotFoundException.class); + } } \ No newline at end of file diff --git a/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfServiceTest.java b/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfServiceTest.java index 7015c200..f696e0e2 100644 --- a/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfServiceTest.java +++ b/src/test/java/toy/bookchat/bookchat/domain/bookshelf/service/BookShelfServiceTest.java @@ -1,8 +1,9 @@ package toy.bookchat.bookchat.domain.bookshelf.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -15,7 +16,6 @@ import java.time.LocalDate; import java.util.List; -import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -24,38 +24,32 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import toy.bookchat.bookchat.domain.agony.repository.AgonyRecordRepository; -import toy.bookchat.bookchat.domain.agony.repository.AgonyRepository; import toy.bookchat.bookchat.domain.book.Book; -import toy.bookchat.bookchat.domain.book.repository.BookRepository; +import toy.bookchat.bookchat.domain.book.service.BookReader; import toy.bookchat.bookchat.domain.bookshelf.BookShelf; import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus; import toy.bookchat.bookchat.domain.bookshelf.Star; -import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository; import toy.bookchat.bookchat.domain.bookshelf.service.dto.request.BookRequest; import toy.bookchat.bookchat.domain.bookshelf.service.dto.request.BookShelfRequest; import toy.bookchat.bookchat.domain.bookshelf.service.dto.request.ReviseBookShelfRequest; import toy.bookchat.bookchat.domain.bookshelf.service.dto.response.ExistenceBookOnBookShelfResponse; import toy.bookchat.bookchat.domain.bookshelf.service.dto.response.SearchBookShelfByReadingStatus; import toy.bookchat.bookchat.domain.user.User; -import toy.bookchat.bookchat.domain.user.repository.UserRepository; -import toy.bookchat.bookchat.exception.notfound.book.BookNotFoundException; +import toy.bookchat.bookchat.domain.user.service.UserReader; @ExtendWith(MockitoExtension.class) class BookShelfServiceTest { @Mock - UserRepository userRepository; + private BookShelfManager bookShelfManager; @Mock - BookRepository bookRepository; + private BookShelfReader bookShelfReader; @Mock - BookShelfRepository bookShelfRepository; + private BookReader bookReader; @Mock - AgonyRepository agonyRepository; - @Mock - AgonyRecordRepository agonyRecordRepository; + private UserReader userReader; @InjectMocks - BookShelfService bookShelfService; + private BookShelfService bookShelfService; private Book getBook() { return Book.builder() @@ -99,62 +93,16 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { } @Test - void 내부에_등록된_책을_책장에_저장() throws Exception { - BookShelfRequest bookShelfRequest = getBookShelfRequest(READING); - Book book = getBook(); - - when(bookRepository.findByIsbnAndPublishAt(any(), any())).thenReturn( - Optional.of(book)); - when(userRepository.findById(any())).thenReturn(Optional.of(mock(User.class))); - - bookShelfService.putBookOnBookShelf(bookShelfRequest, 1L); - - verify(bookShelfRepository).save(any(BookShelf.class)); - } - - @Test - void 내부에_등록되지_않은_책을_책장에_저장() throws Exception { - BookShelfRequest bookShelfRequest = getBookShelfRequest(READING); - - when(bookRepository.findByIsbnAndPublishAt(any(), any())).thenReturn(Optional.empty()); - when(userRepository.findById(any())).thenReturn(Optional.of(mock(User.class))); - bookShelfService.putBookOnBookShelf(bookShelfRequest, 1L); - - verify(bookRepository).save(any(Book.class)); - verify(bookShelfRepository).save(any(BookShelf.class)); - } - - @Test - void 읽은_책_저장_성공() throws Exception { + void 서재에_책_저장_성공() throws Exception { BookShelfRequest bookShelfRequest = getBookShelfRequest(COMPLETE); - Book book = getBook(); - - when(bookRepository.findByIsbnAndPublishAt(any(), any())).thenReturn( - Optional.of(book)); - when(userRepository.findById(any())).thenReturn(Optional.of(mock(User.class))); bookShelfService.putBookOnBookShelf(bookShelfRequest, 1L); - verify(bookShelfRepository).save(any(BookShelf.class)); - } - - @Test - void 읽은_책_저장시_평점_없으면_예외발생() throws Exception { - BookShelfRequest bookShelfRequest = BookShelfRequest.builder() - .bookRequest(getBookRequest()) - .readingStatus(COMPLETE) - .build(); - - when(bookRepository.findByIsbnAndPublishAt(any(), any())).thenReturn(Optional.empty()); - when(userRepository.findById(any())).thenReturn(Optional.of(mock(User.class))); - - assertThatThrownBy(() -> { - bookShelfService.putBookOnBookShelf(bookShelfRequest, 1L); - }).isInstanceOf(IllegalStateException.class); + verify(bookShelfManager).store(any(BookShelf.class)); } @Test - void 읽고있는_책을_조회_성공() throws Exception { + void 도서_상태에따라_서재에서_조회_성공() throws Exception { Pageable pageable = mock(Pageable.class); User user = getUser(); Book book = Book.builder() @@ -164,93 +112,39 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { .publisher("jpub") .bookCoverImageUrl("testBookCoverImageUrl") .build(); - BookShelf bookShelf = BookShelf.builder() .user(user) .book(book) - .readingStatus(READING) - .pages(252) + .readingStatus(WISH) + .pages(0) .star(null) .build(); Page bookShelves = new PageImpl<>(List.of(bookShelf), pageable, 1); + when(bookShelfReader.readBookShelf(user.getId(), WISH, pageable)).thenReturn(bookShelves); - when(bookShelfRepository.findSpecificStatusBookByUserId(any(), any(), any())).thenReturn( - bookShelves); SearchBookShelfByReadingStatus searchBookShelfByReadingStatus = bookShelfService.takeBooksOutOfBookShelves( - READING, pageable, 1L); - - verify(bookShelfRepository).findSpecificStatusBookByUserId(READING, pageable, 1L); - - assertThat(searchBookShelfByReadingStatus.getContents().get(0).getIsbn()).isEqualTo( - "1234"); - } - - @Test - void 읽은_책을_조회_성공() throws Exception { - Pageable pageable = mock(Pageable.class); - User user = getUser(); - Book book = Book.builder() - .isbn("1234") - .title("toby's Spring") - .authors(List.of("이일민")) - .publisher("jpub") - .bookCoverImageUrl("testBookCoverImageUrl") - .build(); - - BookShelf bookShelf = BookShelf.builder() - .user(user) - .book(book) - .readingStatus(COMPLETE) - .pages(0) - .star(FIVE) - .build(); - - Page bookShelves = new PageImpl<>(List.of(bookShelf), pageable, 1); - - when(bookShelfRepository.findSpecificStatusBookByUserId(any(), any(), any())).thenReturn( - bookShelves); - - SearchBookShelfByReadingStatus searchBookShelfByReadingStatus = bookShelfService.takeBooksOutOfBookShelves( - COMPLETE, pageable, user.getId()); - - verify(bookShelfRepository).findSpecificStatusBookByUserId(COMPLETE, pageable, - user.getId()); + WISH, pageable, user.getId()); - assertThat(searchBookShelfByReadingStatus.getContents().get(0).getIsbn()).isEqualTo( - "1234"); + assertThat(searchBookShelfByReadingStatus.getContents().get(0).getIsbn()).isEqualTo("1234"); } @Test - void 읽을_책을_조회_성공() throws Exception { - Pageable pageable = mock(Pageable.class); - User user = getUser(); - Book book = Book.builder() - .isbn("1234") - .title("toby's Spring") - .authors(List.of("이일민")) - .publisher("jpub") - .bookCoverImageUrl("testBookCoverImageUrl") - .build(); + void 책이_서재에_등록되어있다면_응답성공() throws Exception { + Book book = getBook(); BookShelf bookShelf = BookShelf.builder() - .user(user) + .id(1L) .book(book) .readingStatus(WISH) - .pages(0) - .star(null) .build(); - Page bookShelves = new PageImpl<>(List.of(bookShelf), pageable, 1); - when(bookShelfRepository.findSpecificStatusBookByUserId(any(), any(), any())).thenReturn( - bookShelves); + when(bookShelfReader.readBookShelf(anyLong(), anyString(), any(LocalDate.class))).thenReturn(bookShelf); - SearchBookShelfByReadingStatus searchBookShelfByReadingStatus = bookShelfService.takeBooksOutOfBookShelves( - WISH, pageable, user.getId()); + ExistenceBookOnBookShelfResponse result = bookShelfService.getBookIfExisted(book.getIsbn(), book.getPublishAt(), book.getId()); - verify(bookShelfRepository).findSpecificStatusBookByUserId(WISH, pageable, user.getId()); + ExistenceBookOnBookShelfResponse expect = ExistenceBookOnBookShelfResponse.from(bookShelf); - assertThat(searchBookShelfByReadingStatus.getContents().get(0).getIsbn()).isEqualTo( - "1234"); + assertThat(result).usingRecursiveComparison().isEqualTo(expect); } @Test @@ -267,8 +161,7 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { .star(null) .build(); - when(bookShelfRepository.findByIdAndUserId(any(), any())).thenReturn( - Optional.of(bookShelf)); + when(bookShelfReader.readBookShelf(any(), any())).thenReturn(bookShelf); bookShelfService.reviseBookShelf(1L, reviseBookShelfRequest, 1L); @@ -276,15 +169,6 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { assertThat(result).isEqualTo(123); } - @Test - void 책장에서_책_삭제_성공() throws Exception { - bookShelfService.deleteBookShelf(1L, 1L); - - verify(agonyRecordRepository).deleteByBookShelfIdAndUserId(any(), any()); - verify(agonyRepository).deleteByBookShelfIdAndUserId(any(), any()); - verify(bookShelfRepository).deleteBookShelfByIdAndUserId(any(), any()); - } - @Test void 책장에_책_독서상태_변경_성공() throws Exception { ReviseBookShelfRequest reviseBookShelfRequest = ReviseBookShelfRequest.builder() @@ -297,8 +181,7 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { .readingStatus(WISH) .build(); - when(bookShelfRepository.findByIdAndUserId(any(), any())).thenReturn( - Optional.of(bookShelf)); + when(bookShelfReader.readBookShelf(any(), any())).thenReturn(bookShelf); bookShelfService.reviseBookShelf(1L, reviseBookShelfRequest, 1L); @@ -306,13 +189,6 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { assertThat(readingStatus).isEqualTo(READING); } - @Test - void 서재에_등록하지_않은_책_상태변경시도시_예외발생() throws Exception { - assertThatThrownBy(() -> { - bookShelfService.reviseBookShelf(1L, mock(ReviseBookShelfRequest.class), 1L); - }).isInstanceOf(BookNotFoundException.class); - } - @Test void 독서완료_서재_별점수정_성공() throws Exception { ReviseBookShelfRequest reviseBookShelfRequest = ReviseBookShelfRequest.builder() @@ -326,8 +202,7 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { .readingStatus(COMPLETE) .build(); - when(bookShelfRepository.findByIdAndUserId(any(), any())).thenReturn( - Optional.of(bookShelf)); + when(bookShelfReader.readBookShelf(any(), any())).thenReturn(bookShelf); bookShelfService.reviseBookShelf(1L, reviseBookShelfRequest, 1L); Star result = bookShelf.getStar(); @@ -335,39 +210,17 @@ private BookShelfRequest getBookShelfRequest(ReadingStatus readingStatus) { } @Test - void 사용자의_서재_비우기_성공() throws Exception { - bookShelfService.deleteAllUserBookShelves(any()); + void 책장에서_책_삭제_성공() throws Exception { + bookShelfService.deleteBookShelf(1L, 1L); - verify(bookShelfRepository).deleteAllByUserId(any()); + verify(bookShelfManager).vacate(any(), any()); } - @Test - void 책이_서재에_등록되어있다면_응답성공() throws Exception { - Book book = getBook(); - BookShelf bookShelf = BookShelf.builder() - .id(1L) - .book(book) - .readingStatus(WISH) - .build(); - - when(bookShelfRepository.findByUserIdAndIsbnAndPublishAt(any(), any(), any())).thenReturn( - Optional.of(bookShelf)); - - ExistenceBookOnBookShelfResponse result = bookShelfService.getBookIfExisted( - book.getIsbn(), book.getPublishAt(), book.getId()); - - ExistenceBookOnBookShelfResponse expect = ExistenceBookOnBookShelfResponse.from(bookShelf); - - assertThat(result).usingRecursiveComparison().isEqualTo(expect); - } @Test - void 책이_서재에_등록되어있지않다면_예외발생() throws Exception { - Book book = getBook(); + void 사용자의_서재_비우기_성공() throws Exception { + bookShelfService.deleteAllUserBookShelves(any()); - assertThatThrownBy(() -> { - ExistenceBookOnBookShelfResponse result = bookShelfService.getBookIfExisted( - book.getIsbn(), book.getPublishAt(), book.getId()); - }).isInstanceOf(BookNotFoundException.class); + verify(bookShelfManager).remove(any()); } } diff --git a/src/test/java/toy/bookchat/bookchat/domain/user/service/UserReaderTest.java b/src/test/java/toy/bookchat/bookchat/domain/user/service/UserReaderTest.java new file mode 100644 index 00000000..ab000936 --- /dev/null +++ b/src/test/java/toy/bookchat/bookchat/domain/user/service/UserReaderTest.java @@ -0,0 +1,27 @@ +package toy.bookchat.bookchat.domain.user.service; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import toy.bookchat.bookchat.domain.user.repository.UserRepository; +import toy.bookchat.bookchat.exception.notfound.user.UserNotFoundException; + +@ExtendWith(MockitoExtension.class) +class UserReaderTest { + + @Mock + private UserRepository userRepository; + @InjectMocks + private UserReader userReader; + + @Test + void 유저id로_유저를_찾을수없으면_예외발생() throws Exception { + assertThatThrownBy(() -> { + userReader.readUser(1L); + }).isInstanceOf(UserNotFoundException.class); + } +} \ No newline at end of file