From 687ae9998de07dbee6be84e6adc80a232a907c08 Mon Sep 17 00:00:00 2001 From: siyeonSon <87802191+siyeonSon@users.noreply.github.com> Date: Fri, 28 Jun 2024 22:01:41 +0900 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(api):=20change=20?= =?UTF-8?q?name=20announcement=20->=20notice=20(#490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :recycle: refactor(api): change name announcement -> notice * :recycle: refactor(admin): change name announcement -> notice * :recycle: refactor(admin): do not change name announcement -> notice --- .../controller/AnnouncementController.java | 49 ------- .../response/NewAnnouncementResponseDto.java | 12 -- .../repository/AnnouncementRepository.java | 10 -- .../service/AnnouncementService.java | 52 ------- .../notice/controller/NoticeController.java | 49 +++++++ .../dto/response/NewNoticeResponseDto.java | 12 ++ .../dto/response/NoticeListResponseDto.java} | 8 +- .../dto/response/NoticeResponseDto.java} | 8 +- .../notice/repository/NoticeRepository.java | 10 ++ .../domains/notice/service/NoticeService.java | 51 +++++++ .../service/AnnouncementServiceTest.java | 137 ------------------ .../controller/NoticeControllerTest.java} | 96 ++++++------ .../notice/service/NoticeServiceTest.java | 137 ++++++++++++++++++ 13 files changed, 315 insertions(+), 316 deletions(-) delete mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/controller/AnnouncementController.java delete mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/NewAnnouncementResponseDto.java delete mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/repository/AnnouncementRepository.java delete mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/service/AnnouncementService.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/controller/NoticeController.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NewNoticeResponseDto.java rename backend/streetdrop-api/src/main/java/com/depromeet/domains/{announcement/dto/response/AnnouncementListResponseDto.java => notice/dto/response/NoticeListResponseDto.java} (74%) rename backend/streetdrop-api/src/main/java/com/depromeet/domains/{announcement/dto/response/AnnouncementResponseDto.java => notice/dto/response/NoticeResponseDto.java} (80%) create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/repository/NoticeRepository.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/service/NoticeService.java delete mode 100644 backend/streetdrop-api/src/test/java/unit/domains/announcement/service/AnnouncementServiceTest.java rename backend/streetdrop-api/src/test/java/unit/domains/{announcement/controller/AnnouncementControllerTest.java => notice/controller/NoticeControllerTest.java} (53%) create mode 100644 backend/streetdrop-api/src/test/java/unit/domains/notice/service/NoticeServiceTest.java diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/controller/AnnouncementController.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/controller/AnnouncementController.java deleted file mode 100644 index 0e29027d..00000000 --- a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/controller/AnnouncementController.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.depromeet.domains.announcement.controller; - -import com.depromeet.common.dto.PaginationResponseDto; -import com.depromeet.common.dto.ResponseDto; -import com.depromeet.domains.announcement.dto.response.AnnouncementResponseDto; -import com.depromeet.domains.announcement.dto.response.NewAnnouncementResponseDto; -import com.depromeet.domains.announcement.service.AnnouncementService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequestMapping("/announcements") -@RequiredArgsConstructor -@Tag(name = "🔈Announcement", description = "Announcement API") -public class AnnouncementController { - - private final AnnouncementService announcementService; - - @Operation(summary = "공지사항 전체 조회") - @GetMapping - public ResponseEntity> getAnnouncements() { - var response = announcementService.getAnnouncements(); - return ResponseDto.ok(response); - } - - @Operation(summary = "공지사항 단건 조회") - @GetMapping("{announcementId}") - public ResponseEntity getAnnouncement( - @PathVariable(value = "announcementId") Long announcementId - ) { - var response = announcementService.getAnnouncement(announcementId); - return ResponseDto.ok(response); - } - - @Operation(summary = "신규 공지사항 여부 조회") - @GetMapping("/new") - public ResponseEntity hasNewAnnouncement( - @Schema(description = "마지막으로 조회한 공지사항 아이디", example = "1") - @RequestParam(defaultValue = "-1") Long lastAnnouncementId - ) { - var response = announcementService.hasNewAnnouncement(lastAnnouncementId); - return ResponseDto.ok(response); - } - -} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/NewAnnouncementResponseDto.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/NewAnnouncementResponseDto.java deleted file mode 100644 index 9bae71d4..00000000 --- a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/NewAnnouncementResponseDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.depromeet.domains.announcement.dto.response; - -import io.swagger.v3.oas.annotations.media.Schema; - -public record NewAnnouncementResponseDto ( - @Schema(description = "새로운 공지사항이 있는지 여부", example = "true") - boolean hasNewAnnouncement -){ - public NewAnnouncementResponseDto(boolean hasNewAnnouncement) { - this.hasNewAnnouncement = hasNewAnnouncement; - } -} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/repository/AnnouncementRepository.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/repository/AnnouncementRepository.java deleted file mode 100644 index 778489b6..00000000 --- a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/repository/AnnouncementRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.depromeet.domains.announcement.repository; - -import com.depromeet.announcement.Announcement; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface AnnouncementRepository extends JpaRepository { - - boolean existsByIdGreaterThan(Long lastAnnouncementId); - -} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/service/AnnouncementService.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/service/AnnouncementService.java deleted file mode 100644 index 0f13edc4..00000000 --- a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/service/AnnouncementService.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.depromeet.domains.announcement.service; - -import com.depromeet.common.dto.MetaInterface; -import com.depromeet.common.dto.PageMetaResponseDto; -import com.depromeet.common.dto.PaginationResponseDto; -import com.depromeet.common.error.dto.CommonErrorCode; -import com.depromeet.common.error.exception.internal.NotFoundException; -import com.depromeet.domains.announcement.dto.response.AnnouncementListResponseDto; -import com.depromeet.domains.announcement.dto.response.AnnouncementResponseDto; -import com.depromeet.domains.announcement.dto.response.NewAnnouncementResponseDto; -import com.depromeet.domains.announcement.repository.AnnouncementRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@Service -public class AnnouncementService { - - private final AnnouncementRepository announcementRepository; - - @Transactional(readOnly = true) - public PaginationResponseDto getAnnouncements() { - var announcements = announcementRepository.findAll() - .stream() - .map(AnnouncementListResponseDto::new) - .toList(); - var meta = PageMetaResponseDto.builder() - .page(1) - .size(announcements.size()) - .totalPage(1) - .firstPage(true) - .lastPage(true) - .build(); - return new PaginationResponseDto<>(announcements, meta); - } - - @Transactional(readOnly = true) - public AnnouncementResponseDto getAnnouncement(Long announcementId) { - return announcementRepository.findById(announcementId) - .map(AnnouncementResponseDto::new) - .orElseThrow(() -> new NotFoundException(CommonErrorCode.NOT_FOUND, announcementId)); - } - - - @Transactional(readOnly = true) - public NewAnnouncementResponseDto hasNewAnnouncement(Long lastAnnouncementId) { - var isExist = announcementRepository.existsByIdGreaterThan(lastAnnouncementId); - return new NewAnnouncementResponseDto(isExist); - } - -} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/controller/NoticeController.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/controller/NoticeController.java new file mode 100644 index 00000000..7823e1bb --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/controller/NoticeController.java @@ -0,0 +1,49 @@ +package com.depromeet.domains.notice.controller; + +import com.depromeet.common.dto.PaginationResponseDto; +import com.depromeet.common.dto.ResponseDto; +import com.depromeet.domains.notice.dto.response.NoticeResponseDto; +import com.depromeet.domains.notice.dto.response.NewNoticeResponseDto; +import com.depromeet.domains.notice.service.NoticeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/notices") +@RequiredArgsConstructor +@Tag(name = "🔈Notice", description = "Notice API") +public class NoticeController { + + private final NoticeService noticeService; + + @Operation(summary = "공지사항 전체 조회") + @GetMapping + public ResponseEntity> getNotices() { + var response = noticeService.getNotices(); + return ResponseDto.ok(response); + } + + @Operation(summary = "공지사항 단건 조회") + @GetMapping("{noticeId}") + public ResponseEntity getNotice( + @PathVariable(value = "noticeId") Long noticeId + ) { + var response = noticeService.getNotice(noticeId); + return ResponseDto.ok(response); + } + + @Operation(summary = "신규 공지사항 여부 조회") + @GetMapping("/new") + public ResponseEntity hasNewNotice( + @Schema(description = "마지막으로 조회한 공지사항 아이디", example = "1") + @RequestParam(defaultValue = "-1") Long lastNoticeId + ) { + var response = noticeService.hasNewNotice(lastNoticeId); + return ResponseDto.ok(response); + } + +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NewNoticeResponseDto.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NewNoticeResponseDto.java new file mode 100644 index 00000000..77872fef --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NewNoticeResponseDto.java @@ -0,0 +1,12 @@ +package com.depromeet.domains.notice.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; + +public record NewNoticeResponseDto( + @Schema(description = "새로운 공지사항이 있는지 여부", example = "true") + boolean hasNewNotice +){ + public NewNoticeResponseDto(boolean hasNewNotice) { + this.hasNewNotice = hasNewNotice; + } +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/AnnouncementListResponseDto.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NoticeListResponseDto.java similarity index 74% rename from backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/AnnouncementListResponseDto.java rename to backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NoticeListResponseDto.java index f6776097..16a04ff2 100644 --- a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/AnnouncementListResponseDto.java +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NoticeListResponseDto.java @@ -1,13 +1,13 @@ -package com.depromeet.domains.announcement.dto.response; +package com.depromeet.domains.notice.dto.response; import com.depromeet.announcement.Announcement; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; -public record AnnouncementListResponseDto( +public record NoticeListResponseDto( @Schema(description = "공지사항 아이디", example = "1") - Long announcementId, + Long noticeId, @Schema(description = "공지사항 제목", example = "사용성 개선") String title, @@ -15,7 +15,7 @@ public record AnnouncementListResponseDto( @Schema(description = "생성시간", example = "yyyy-MM-dd HH:mm:ss") LocalDateTime createdAt ) { - public AnnouncementListResponseDto(Announcement announcement) { + public NoticeListResponseDto(Announcement announcement) { this( announcement.getId(), announcement.getTitle(), diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/AnnouncementResponseDto.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NoticeResponseDto.java similarity index 80% rename from backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/AnnouncementResponseDto.java rename to backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NoticeResponseDto.java index 77ec6042..38b19b33 100644 --- a/backend/streetdrop-api/src/main/java/com/depromeet/domains/announcement/dto/response/AnnouncementResponseDto.java +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/dto/response/NoticeResponseDto.java @@ -1,12 +1,12 @@ -package com.depromeet.domains.announcement.dto.response; +package com.depromeet.domains.notice.dto.response; import com.depromeet.announcement.Announcement; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; -public record AnnouncementResponseDto( +public record NoticeResponseDto( @Schema(description = "공지사항 아이디", example = "1") - Long announcementId, + Long noticeId, @Schema(description = "공지사항 제목", example = "사용성 개선") String title, @@ -17,7 +17,7 @@ public record AnnouncementResponseDto( @Schema(description = "생성시간", example = "yyyy-MM-dd HH:mm:ss") LocalDateTime createdAt ) { - public AnnouncementResponseDto(Announcement announcement) { + public NoticeResponseDto(Announcement announcement) { this( announcement.getId(), announcement.getTitle(), diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/repository/NoticeRepository.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/repository/NoticeRepository.java new file mode 100644 index 00000000..81326ec4 --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/repository/NoticeRepository.java @@ -0,0 +1,10 @@ +package com.depromeet.domains.notice.repository; + +import com.depromeet.announcement.Announcement; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface NoticeRepository extends JpaRepository { + + boolean existsByIdGreaterThan(Long lastNoticeId); + +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/service/NoticeService.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/service/NoticeService.java new file mode 100644 index 00000000..0fa966c8 --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/notice/service/NoticeService.java @@ -0,0 +1,51 @@ +package com.depromeet.domains.notice.service; + +import com.depromeet.common.dto.MetaInterface; +import com.depromeet.common.dto.PageMetaResponseDto; +import com.depromeet.common.dto.PaginationResponseDto; +import com.depromeet.common.error.dto.CommonErrorCode; +import com.depromeet.common.error.exception.internal.NotFoundException; +import com.depromeet.domains.notice.dto.response.NoticeListResponseDto; +import com.depromeet.domains.notice.dto.response.NoticeResponseDto; +import com.depromeet.domains.notice.dto.response.NewNoticeResponseDto; +import com.depromeet.domains.notice.repository.NoticeRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Service +public class NoticeService { + + private final NoticeRepository noticeRepository; + + @Transactional(readOnly = true) + public PaginationResponseDto getNotices() { + var notices = noticeRepository.findAll() + .stream() + .map(NoticeListResponseDto::new) + .toList(); + var meta = PageMetaResponseDto.builder() + .page(1) + .size(notices.size()) + .totalPage(1) + .firstPage(true) + .lastPage(true) + .build(); + return new PaginationResponseDto<>(notices, meta); + } + + @Transactional(readOnly = true) + public NoticeResponseDto getNotice(Long noticeId) { + return noticeRepository.findById(noticeId) + .map(NoticeResponseDto::new) + .orElseThrow(() -> new NotFoundException(CommonErrorCode.NOT_FOUND, noticeId)); + } + + @Transactional(readOnly = true) + public NewNoticeResponseDto hasNewNotice(Long lastNoticeId) { + var isExist = noticeRepository.existsByIdGreaterThan(lastNoticeId); + return new NewNoticeResponseDto(isExist); + } + +} diff --git a/backend/streetdrop-api/src/test/java/unit/domains/announcement/service/AnnouncementServiceTest.java b/backend/streetdrop-api/src/test/java/unit/domains/announcement/service/AnnouncementServiceTest.java deleted file mode 100644 index f04b9174..00000000 --- a/backend/streetdrop-api/src/test/java/unit/domains/announcement/service/AnnouncementServiceTest.java +++ /dev/null @@ -1,137 +0,0 @@ -package unit.domains.announcement.service; - -import com.depromeet.announcement.Announcement; -import com.depromeet.common.error.exception.internal.NotFoundException; -import com.depromeet.domains.announcement.dto.response.AnnouncementListResponseDto; -import com.depromeet.domains.announcement.dto.response.AnnouncementResponseDto; -import com.depromeet.domains.announcement.dto.response.NewAnnouncementResponseDto; -import com.depromeet.domains.announcement.repository.AnnouncementRepository; -import com.depromeet.domains.announcement.service.AnnouncementService; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -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 java.util.List; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -@DisplayName("[Service] AnnouncementService 테스트") -class AnnouncementServiceTest { - - @InjectMocks - AnnouncementService announcementService; - - @Mock - AnnouncementRepository announcementRepository; - - @DisplayName("공지사항 전체 조회") - @Nested - class GetAnnouncementsTest { - @Nested - @DisplayName("성공") - class Success { - @DisplayName("공지사항 0개 조회") - @Test - void getAnnouncementsTestSuccess1() { - when(announcementRepository.findAll()).thenReturn(List.of()); - - var result = announcementService.getAnnouncements(); - - assertThat(result.getData()).isEmpty(); - } - - @DisplayName("공지사항 2개 조회") - @Test - void getAnnouncementsTestSuccess2() { - List announcements = List.of( - new Announcement("Title 1", "Content 1"), - new Announcement("Title 2", "Content 2") - ); - when(announcementRepository.findAll()).thenReturn(announcements); - - var result = announcementService.getAnnouncements(); - - assertThat(result.getData()).isEqualTo( - List.of( - new AnnouncementListResponseDto(announcements.get(0)), - new AnnouncementListResponseDto(announcements.get(1)) - ) - ); - } - } - } - - @DisplayName("공지사항 단건 조회") - @Nested - class GetAnnouncementTest { - @Nested - @DisplayName("성공") - class Success { - @DisplayName("id가 일치하는 경우") - @Test - void getAnnouncementTestSuccess1() { - var announcement = new Announcement("Title 1", "Content 1"); - when(announcementRepository.findById(1L)).thenReturn(Optional.of(announcement)); - - var result = announcementService.getAnnouncement(1L); - - assertThat(result).isEqualTo( - new AnnouncementResponseDto(announcement) - ); - } - } - - @Nested - @DisplayName("실패") - class Fail { - @DisplayName("id가 일치하지 않는 경우") - @Test - void getAnnouncementTestFail1() { - var announcementId = 1L; - - when(announcementRepository.findById(announcementId)).thenReturn(Optional.empty()); - when(announcementRepository.findById(1L)).thenReturn(Optional.empty()); - - assertThatThrownBy(() -> announcementService.getAnnouncement(announcementId)) - .isInstanceOf(NotFoundException.class); - } - } - } - - - @DisplayName("신규 공지사항 여부 조회") - @Nested - class HasNewAnnouncementTest { - @DisplayName("조회할 공지사항 있는 경우") - @Test - void hasNewAnnouncementTestSuccess1() { - var expectedResponse = new NewAnnouncementResponseDto(true); - - when(announcementRepository.existsByIdGreaterThan(-1L)).thenReturn(true); - - var result = announcementService.hasNewAnnouncement(-1L); - - assertThat(result).isEqualTo(expectedResponse); - } - - @DisplayName("조회할 공지사항 없는 경우") - @Test - void hasNewAnnouncementTestSuccess2() { - var expectedResponse = new NewAnnouncementResponseDto(false); - - when(announcementRepository.existsByIdGreaterThan(-1L)).thenReturn(false); - - var result = announcementService.hasNewAnnouncement(-1L); - - assertThat(result).isEqualTo(expectedResponse); - } - } -} diff --git a/backend/streetdrop-api/src/test/java/unit/domains/announcement/controller/AnnouncementControllerTest.java b/backend/streetdrop-api/src/test/java/unit/domains/notice/controller/NoticeControllerTest.java similarity index 53% rename from backend/streetdrop-api/src/test/java/unit/domains/announcement/controller/AnnouncementControllerTest.java rename to backend/streetdrop-api/src/test/java/unit/domains/notice/controller/NoticeControllerTest.java index 55d5f2c2..9feb96ea 100644 --- a/backend/streetdrop-api/src/test/java/unit/domains/announcement/controller/AnnouncementControllerTest.java +++ b/backend/streetdrop-api/src/test/java/unit/domains/notice/controller/NoticeControllerTest.java @@ -1,4 +1,4 @@ -package unit.domains.announcement.controller; +package unit.domains.notice.controller; import com.depromeet.announcement.Announcement; import com.depromeet.common.dto.MetaInterface; @@ -7,11 +7,11 @@ import com.depromeet.common.error.GlobalExceptionHandler; import com.depromeet.common.error.dto.CommonErrorCode; import com.depromeet.common.error.exception.internal.NotFoundException; -import com.depromeet.domains.announcement.controller.AnnouncementController; -import com.depromeet.domains.announcement.dto.response.AnnouncementListResponseDto; -import com.depromeet.domains.announcement.dto.response.AnnouncementResponseDto; -import com.depromeet.domains.announcement.dto.response.NewAnnouncementResponseDto; -import com.depromeet.domains.announcement.service.AnnouncementService; +import com.depromeet.domains.notice.controller.NoticeController; +import com.depromeet.domains.notice.dto.response.NoticeListResponseDto; +import com.depromeet.domains.notice.dto.response.NoticeResponseDto; +import com.depromeet.domains.notice.dto.response.NewNoticeResponseDto; +import com.depromeet.domains.notice.service.NoticeService; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -30,27 +30,27 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ContextConfiguration(classes = AnnouncementController.class) -@WebMvcTest(controllers = {AnnouncementController.class}, excludeAutoConfiguration = {SecurityAutoConfiguration.class}) -@Import({AnnouncementController.class, GlobalExceptionHandler.class}) -@DisplayName("[API][Controller] AnnouncementController 테스트") -public class AnnouncementControllerTest { +@ContextConfiguration(classes = NoticeController.class) +@WebMvcTest(controllers = {NoticeController.class}, excludeAutoConfiguration = {SecurityAutoConfiguration.class}) +@Import({NoticeController.class, GlobalExceptionHandler.class}) +@DisplayName("[API][Controller] NoticeController 테스트") +public class NoticeControllerTest { @Autowired MockMvc mvc; @MockBean - AnnouncementService announcementService; + NoticeService noticeService; @DisplayName("[GET] 공지사항 전체 조회") @Nested - class GetAnnouncementsTest { + class GetNoticesTest { @Nested @DisplayName("성공") class Success { @DisplayName("공지사항 0개 조회") @Test - void getAnnouncementsTestSuccess1() throws Exception { + void getNoticesTestSuccess1() throws Exception { var meta = PageMetaResponseDto.builder() .page(0) .size(0) @@ -58,10 +58,10 @@ void getAnnouncementsTestSuccess1() throws Exception { .firstPage(true) .lastPage(true) .build(); - PaginationResponseDto paginationResponseDto = new PaginationResponseDto<>(List.of(), meta); - when(announcementService.getAnnouncements()).thenReturn(paginationResponseDto); + PaginationResponseDto paginationResponseDto = new PaginationResponseDto<>(List.of(), meta); + when(noticeService.getNotices()).thenReturn(paginationResponseDto); - var response = mvc.perform(get("/announcements")); + var response = mvc.perform(get("/notices")); response.andExpect(status().isOk()) .andExpect(jsonPath("$.data").isArray()) .andExpect(jsonPath("$.data.length()").value(0)) @@ -74,10 +74,10 @@ void getAnnouncementsTestSuccess1() throws Exception { @DisplayName("공지사항 2개 조회") @Test - void getAnnouncementsTestSuccess2() throws Exception { - var announcementResponseDto = List.of( - new AnnouncementListResponseDto(new Announcement("Title 1", "Content 1")), - new AnnouncementListResponseDto(new Announcement("Title 2", "Content 2")) + void getNoticesTestSuccess2() throws Exception { + var noticeResponseDto = List.of( + new NoticeListResponseDto(new Announcement("Title 1", "Content 1")), + new NoticeListResponseDto(new Announcement("Title 2", "Content 2")) ); var meta = PageMetaResponseDto.builder() .page(0) @@ -86,10 +86,10 @@ void getAnnouncementsTestSuccess2() throws Exception { .firstPage(true) .lastPage(true) .build(); - PaginationResponseDto paginationResponseDto = new PaginationResponseDto<>(announcementResponseDto, meta); - when(announcementService.getAnnouncements()).thenReturn(paginationResponseDto); + PaginationResponseDto paginationResponseDto = new PaginationResponseDto<>(noticeResponseDto, meta); + when(noticeService.getNotices()).thenReturn(paginationResponseDto); - var response = mvc.perform(get("/announcements")); + var response = mvc.perform(get("/notices")); response.andExpect(status().isOk()) .andExpect(jsonPath("$.data").isArray()) .andExpect(jsonPath("$.data.length()").value(2)) @@ -101,18 +101,18 @@ void getAnnouncementsTestSuccess2() throws Exception { @DisplayName("[GET] 공지사항 단건 조회") @Nested - class GetAnnouncementTest { + class GetNoticeTest { @Nested @DisplayName("성공") class Success { @DisplayName("id가 일치하는 경우") @Test - void getAnnouncementTestSuccess1() throws Exception { - var announcementId = 1L; - var announcementResponseDto = new AnnouncementResponseDto(new Announcement("Title 1", "Content 1")); - when(announcementService.getAnnouncement(announcementId)).thenReturn(announcementResponseDto); + void getNoticeTestSuccess1() throws Exception { + var noticeId = 1L; + var noticeResponseDto = new NoticeResponseDto(new Announcement("Title 1", "Content 1")); + when(noticeService.getNotice(noticeId)).thenReturn(noticeResponseDto); - var response = mvc.perform(get("/announcements/{announcementId}", announcementId)); + var response = mvc.perform(get("/notices/{noticeId}", noticeId)); response.andExpect(status().isOk()) .andExpect(jsonPath("$.title").value("Title 1")) .andExpect(jsonPath("$.content").value("Content 1")); @@ -124,12 +124,12 @@ void getAnnouncementTestSuccess1() throws Exception { class Fail { @DisplayName("id가 일치하지 않는 경우") @Test - void getAnnouncementTestFail1() throws Exception { - var announcementId = 1L; - when(announcementService.getAnnouncement(announcementId)) - .thenThrow(new NotFoundException(CommonErrorCode.NOT_FOUND, announcementId)); + void getNoticeTestFail1() throws Exception { + var noticeId = 1L; + when(noticeService.getNotice(noticeId)) + .thenThrow(new NotFoundException(CommonErrorCode.NOT_FOUND, noticeId)); - var response = mvc.perform(get("/announcements/{announcementId}", announcementId)); + var response = mvc.perform(get("/notices/{noticeId}", noticeId)); response.andExpect(status().isNotFound()); } } @@ -138,33 +138,33 @@ void getAnnouncementTestFail1() throws Exception { @DisplayName("[GET] 신규 공지사항 여부 조회") @Nested - class HasNewAnnouncementTest { + class HasNewNoticeTest { @Nested @DisplayName("성공") class Success { @DisplayName("신규 공지사항이 없는 경우") @Test - void hasNewAnnouncementTestSuccess1() throws Exception { - var lastAnnouncementId = 1L; - var announcementResponseDto = new NewAnnouncementResponseDto(false); - when(announcementService.hasNewAnnouncement(lastAnnouncementId)).thenReturn(announcementResponseDto); + void hasNewNoticeTestSuccess1() throws Exception { + var lastNoticeId = 1L; + var newNoticeResponseDto = new NewNoticeResponseDto(false); + when(noticeService.hasNewNotice(lastNoticeId)).thenReturn(newNoticeResponseDto); - var response = mvc.perform(get("/announcements/new?lastAnnouncementId={lastAnnouncementId}", lastAnnouncementId)); + var response = mvc.perform(get("/notices/new?lastNoticeId={lastNoticeId}", lastNoticeId)); response.andExpect(status().isOk()) - .andExpect(jsonPath("$.hasNewAnnouncement").value(false)); + .andExpect(jsonPath("$.hasNewNotice").value(false)); } @DisplayName("신규 공지사항이 있는 경우") @Test - void hasNewAnnouncementTestSuccess2() throws Exception { - var lastAnnouncementId = 1L; - var announcementResponseDto = new NewAnnouncementResponseDto(true); - when(announcementService.hasNewAnnouncement(lastAnnouncementId)).thenReturn(announcementResponseDto); + void hasNewNoticeTestSuccess2() throws Exception { + var lastNoticeId = 1L; + var newNoticeResponseDto = new NewNoticeResponseDto(true); + when(noticeService.hasNewNotice(lastNoticeId)).thenReturn(newNoticeResponseDto); - var response = mvc.perform(get("/announcements/new?lastAnnouncementId={lastAnnouncementId}", lastAnnouncementId)); + var response = mvc.perform(get("/notices/new?lastNoticeId={lastNoticeId}", lastNoticeId)); response.andExpect(status().isOk()) - .andExpect(jsonPath("$.hasNewAnnouncement").value(true)); + .andExpect(jsonPath("$.hasNewNotice").value(true)); } } diff --git a/backend/streetdrop-api/src/test/java/unit/domains/notice/service/NoticeServiceTest.java b/backend/streetdrop-api/src/test/java/unit/domains/notice/service/NoticeServiceTest.java new file mode 100644 index 00000000..52043174 --- /dev/null +++ b/backend/streetdrop-api/src/test/java/unit/domains/notice/service/NoticeServiceTest.java @@ -0,0 +1,137 @@ +package unit.domains.notice.service; + +import com.depromeet.announcement.Announcement; +import com.depromeet.common.error.exception.internal.NotFoundException; +import com.depromeet.domains.notice.dto.response.NoticeListResponseDto; +import com.depromeet.domains.notice.dto.response.NoticeResponseDto; +import com.depromeet.domains.notice.dto.response.NewNoticeResponseDto; +import com.depromeet.domains.notice.repository.NoticeRepository; +import com.depromeet.domains.notice.service.NoticeService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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 java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +@DisplayName("[Service] NoticeService 테스트") +class NoticeServiceTest { + + @InjectMocks + NoticeService noticeService; + + @Mock + NoticeRepository noticeRepository; + + @DisplayName("공지사항 전체 조회") + @Nested + class GetNoticesTest { + @Nested + @DisplayName("성공") + class Success { + @DisplayName("공지사항 0개 조회") + @Test + void getNoticesTestSuccess1() { + when(noticeRepository.findAll()).thenReturn(List.of()); + + var result = noticeService.getNotices(); + + assertThat(result.getData()).isEmpty(); + } + + @DisplayName("공지사항 2개 조회") + @Test + void getNoticesTestSuccess2() { + List notices = List.of( + new Announcement("Title 1", "Content 1"), + new Announcement("Title 2", "Content 2") + ); + when(noticeRepository.findAll()).thenReturn(notices); + + var result = noticeService.getNotices(); + + assertThat(result.getData()).isEqualTo( + List.of( + new NoticeListResponseDto(notices.get(0)), + new NoticeListResponseDto(notices.get(1)) + ) + ); + } + } + } + + @DisplayName("공지사항 단건 조회") + @Nested + class GetNoticeTest { + @Nested + @DisplayName("성공") + class Success { + @DisplayName("id가 일치하는 경우") + @Test + void getNoticeTestSuccess1() { + var notice = new Announcement("Title 1", "Content 1"); + when(noticeRepository.findById(1L)).thenReturn(Optional.of(notice)); + + var result = noticeService.getNotice(1L); + + assertThat(result).isEqualTo( + new NoticeResponseDto(notice) + ); + } + } + + @Nested + @DisplayName("실패") + class Fail { + @DisplayName("id가 일치하지 않는 경우") + @Test + void getNoticeTestFail1() { + var noticeId = 1L; + + when(noticeRepository.findById(noticeId)).thenReturn(Optional.empty()); + when(noticeRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> noticeService.getNotice(noticeId)) + .isInstanceOf(NotFoundException.class); + } + } + } + + + @DisplayName("신규 공지사항 여부 조회") + @Nested + class HasNewNoticeTest { + @DisplayName("조회할 공지사항 있는 경우") + @Test + void hasNewNoticeTestSuccess1() { + var expectedResponse = new NewNoticeResponseDto(true); + + when(noticeRepository.existsByIdGreaterThan(-1L)).thenReturn(true); + + var result = noticeService.hasNewNotice(-1L); + + assertThat(result).isEqualTo(expectedResponse); + } + + @DisplayName("조회할 공지사항 없는 경우") + @Test + void hasNewNoticeTestSuccess2() { + var expectedResponse = new NewNoticeResponseDto(false); + + when(noticeRepository.existsByIdGreaterThan(-1L)).thenReturn(false); + + var result = noticeService.hasNewNotice(-1L); + + assertThat(result).isEqualTo(expectedResponse); + } + } +}