From 5e338102f1f293596273d9f2683c67c7098d2fbe Mon Sep 17 00:00:00 2001 From: parkjaehak Date: Tue, 4 Feb 2025 11:48:09 +0900 Subject: [PATCH 1/7] =?UTF-8?q?CLAP-221=20Add:=20=EC=9E=91=EC=97=85=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/task/FindTaskListServiceTest.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java b/src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java index c389d366..d2e8a63f 100644 --- a/src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java +++ b/src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java @@ -7,9 +7,13 @@ import clap.server.application.port.inbound.domain.MemberService; import clap.server.application.port.outbound.task.LoadTaskPort; import clap.server.domain.model.task.Task; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; +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.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; @@ -22,7 +26,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; -//@ExtendWith(MockitoExtension.class) +@ExtendWith(MockitoExtension.class) class FindTaskListServiceTest { @Mock @@ -37,7 +41,7 @@ class FindTaskListServiceTest { private PageResponse expectedResponse; private Page pageResponse; - //@BeforeEach + @BeforeEach void setUp() { pageable = PageRequest.of(0, 20); filterTaskListRequest = new FilterTaskListRequest( @@ -62,7 +66,7 @@ void setUp() { expectedResponse = PageResponse.from(pageResponse.map(TaskResponseMapper::toFilterPendingApprovalTasksResponse)); } - //@Test + @Test @DisplayName("승인대기 중인 작업요청목록 조회 - 정상적인 데이터 반환") void findPendingApprovalTasks_ReturnFilteredTasks() { // given From f2682dfe219be73d996a5fb411a040cf0fbe0d85 Mon Sep 17 00:00:00 2001 From: parkjaehak Date: Tue, 4 Feb 2025 12:53:37 +0900 Subject: [PATCH 2/7] =?UTF-8?q?CLAP-221=20Feat:=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EC=9E=91=EC=97=85=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/task/FindTaskListServiceTest.java | 129 ---------------- .../task/FindTasksRequestedByUserTest.java | 139 ++++++++++++++++++ 2 files changed, 139 insertions(+), 129 deletions(-) delete mode 100644 src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java create mode 100644 src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java diff --git a/src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java b/src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java deleted file mode 100644 index d2e8a63f..00000000 --- a/src/test/java/clap/server/application/service/task/FindTaskListServiceTest.java +++ /dev/null @@ -1,129 +0,0 @@ -package clap.server.application.service.task; - -import clap.server.adapter.inbound.web.dto.common.PageResponse; -import clap.server.adapter.inbound.web.dto.task.request.FilterTaskListRequest; -import clap.server.adapter.inbound.web.dto.task.response.FilterPendingApprovalResponse; -import clap.server.application.mapper.TaskResponseMapper; -import clap.server.application.port.inbound.domain.MemberService; -import clap.server.application.port.outbound.task.LoadTaskPort; -import clap.server.domain.model.task.Task; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -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.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; - -import java.time.LocalDateTime; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class FindTaskListServiceTest { - - @Mock - private MemberService memberService; - @Mock - private LoadTaskPort loadTaskPort; - @InjectMocks - private FindTaskListService findTaskListService; - - private FilterTaskListRequest filterTaskListRequest; - private Pageable pageable; - private PageResponse expectedResponse; - private Page pageResponse; - - @BeforeEach - void setUp() { - pageable = PageRequest.of(0, 20); - filterTaskListRequest = new FilterTaskListRequest( - null, List.of(2L), List.of(1L), "작업 제목", "", List.of(), "REQUESTED_AT", "DESC" - ); - Task task1 = Task.builder() - .taskId(1L) - .taskCode("TC001") - .title("작업 제목") - .dueDate(LocalDateTime.of(2025, 1, 24, 12, 30)) - .build(); - - Task task2 = Task.builder() - .taskId(2L) - .taskCode("TC002") - .title("다른 작업 제목") - .dueDate(LocalDateTime.of(2025, 1, 15, 14, 30)) - .build(); - - - pageResponse = new PageImpl<>(List.of(task1, task2), pageable, 2); - expectedResponse = PageResponse.from(pageResponse.map(TaskResponseMapper::toFilterPendingApprovalTasksResponse)); - } - - @Test - @DisplayName("승인대기 중인 작업요청목록 조회 - 정상적인 데이터 반환") - void findPendingApprovalTasks_ReturnFilteredTasks() { - // given - Long managerId = 1L; - when(loadTaskPort.findTasksRequestedByUser(eq(managerId), eq(pageable), eq(filterTaskListRequest))) - .thenReturn(pageResponse); - - // when - PageResponse result = findTaskListService.findPendingApprovalTasks(managerId, pageable, filterTaskListRequest); - - // then - assertThat(result).isNotNull(); - assertThat(result.totalElements()).isEqualTo(2); - assertThat(result.content()).hasSize(2) - .extracting(FilterPendingApprovalResponse::taskId) - .containsExactly(1L, 2L); - } - - //@Test - @DisplayName("승인대기 중인 작업요청목록 조회 - 필터 조건에 맞는 작업 없음") - void findPendingApprovalTasks_NoTasksFound() { - // given - Long managerId = 1L; - FilterTaskListRequest filterWithNoResults = new FilterTaskListRequest( - null, List.of(999L), List.of(1000L), "없는 작업 제목", "", List.of(), "REQUESTED_AT", "DESC" - ); - when(loadTaskPort.findTasksRequestedByUser(eq(managerId), eq(pageable), eq(filterWithNoResults))) - .thenReturn(Page.empty()); - - // when - PageResponse result = findTaskListService.findPendingApprovalTasks(managerId, pageable, filterWithNoResults); - - // then - assertThat(result).isNotNull(); - assertThat(result.totalElements()).isEqualTo(0); - assertThat(result.content()).isEmpty(); - } - - //@Test - @DisplayName("승인대기 중인 작업요청목록 조회 - 필터 조건에 따른 정확한 결과 반환") - void findPendingApprovalTasks_FilterByTitle() { - // given - Long managerId = 1L; - FilterTaskListRequest filterByTitle = new FilterTaskListRequest( - null, List.of(2L), List.of(1L), "작업 제목", "", List.of(), "REQUESTED_AT", "DESC" - ); - when(loadTaskPort.findTasksRequestedByUser(eq(managerId), eq(pageable), eq(filterByTitle))) - .thenReturn(pageResponse); - - // when - PageResponse result = findTaskListService.findPendingApprovalTasks(managerId, pageable, filterByTitle); - - // then - assertThat(result).isNotNull(); - assertThat(result.totalElements()).isEqualTo(2); - assertThat(result.content()) - .extracting(FilterPendingApprovalResponse::title) - .containsExactly("작업 제목", "다른 작업 제목"); - } -} diff --git a/src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java b/src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java new file mode 100644 index 00000000..0b1f2525 --- /dev/null +++ b/src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java @@ -0,0 +1,139 @@ +package clap.server.application.service.task; + +import clap.server.adapter.inbound.web.dto.common.PageResponse; +import clap.server.adapter.inbound.web.dto.task.request.FilterTaskListRequest; +import clap.server.adapter.inbound.web.dto.task.response.FilterRequestedTasksResponse; +import clap.server.adapter.outbound.persistense.entity.member.constant.MemberStatus; +import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; +import clap.server.application.port.inbound.domain.MemberService; +import clap.server.application.port.outbound.task.LoadTaskPort; +import clap.server.domain.model.member.Member; +import clap.server.domain.model.task.Category; +import clap.server.domain.model.task.Task; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +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.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class FindTasksRequestedByUserTest { + + @Mock + private MemberService memberService; + @Mock + private LoadTaskPort loadTaskPort; + @InjectMocks + private FindTaskListService findTaskListService; + + private FilterTaskListRequest filterTaskListRequest; + private Member member; + private Page taskPage; + private Task task1, task2; + + @BeforeEach + void setUp() { + member = new Member(1L, null, null, + true, false, true, + null, MemberStatus.ACTIVE, null + ); + Category mainCategory = Category.builder() + .categoryId(1L) + .name("1차 카테고리") + .code("VM") + .isDeleted(false) + .descriptionExample("메인 카테고리 입니다.") + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .build(); + Category category = Category.builder() + .categoryId(2L) + .name("2차 카테고리") + .code("CR") + .isDeleted(false) + .descriptionExample("서브 카테고리 입니다.") + .mainCategory(mainCategory) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .build(); + task1 = Task.builder() + .taskId(1L) + .taskCode("TC001") + .title("제목1") + .description("설명1") + .category(category) + .taskStatus(TaskStatus.REQUESTED) + .finishedAt(null) + .build(); + task2 = Task.builder() + .taskId(2L) + .taskCode("TC002") + .title("제목2") + .description("설명2") + .category(category) + .taskStatus(TaskStatus.COMPLETED) + .finishedAt(LocalDateTime.of(2025,2,4,11,30,11)) + .build(); + + filterTaskListRequest = new FilterTaskListRequest(null, List.of(), List.of(), "", "", List.of(), "", ""); + taskPage = new PageImpl<>(List.of(task1, task2)); + } + + @Test + @DisplayName("요청한 작업 목록 조회") + void findRequestedByUserTasks() { + //given + PageRequest pageable = PageRequest.of(0, 20); + when(memberService.findActiveMember(1L)).thenReturn(member); + when(loadTaskPort.findTasksRequestedByUser(1L, pageable, filterTaskListRequest)) + .thenReturn(taskPage); + //when + PageResponse result = findTaskListService.findTasksRequestedByUser(member.getMemberId(), pageable, filterTaskListRequest); + + //then + assertThat(result.content()).hasSize(2) + .extracting(FilterRequestedTasksResponse::taskId) + .containsExactly(1L, 2L); + + FilterRequestedTasksResponse task1Response = result.content().get(0); + assertThat(task1Response.taskId()).isEqualTo(1L); + assertThat(task1Response.taskCode()).isEqualTo("TC001"); + assertThat(task1Response.mainCategoryName()).isEqualTo("1차 카테고리"); + assertThat(task1Response.categoryName()).isEqualTo("2차 카테고리"); + assertThat(task1Response.title()).isEqualTo("제목1"); + assertThat(task1Response.processorName()).isEqualTo(""); + assertThat(task1Response.taskStatus()).isEqualTo(TaskStatus.REQUESTED); + assertThat(task1Response.finishedAt()).isNull(); + } + + @Test + @DisplayName("요청한 작업 목록 조회 - 카테고리 조건") + void findRequestedByUserTasks_FilteredWithCategory() { + // given + PageRequest pageable = PageRequest.of(0, 20); + filterTaskListRequest = new FilterTaskListRequest(null, List.of(2L), List.of(), "", "", List.of(), "", ""); + taskPage = new PageImpl<>(List.of(task2)); + when(memberService.findActiveMember(1L)).thenReturn(member); + when(loadTaskPort.findTasksRequestedByUser(1L, pageable, filterTaskListRequest)) + .thenReturn(taskPage); + + // when + PageResponse result = findTaskListService.findTasksRequestedByUser(member.getMemberId(), pageable, filterTaskListRequest); + + // then + assertThat(result.content()).hasSize(1); + assertThat(result.content()).extracting(FilterRequestedTasksResponse::categoryName) + .containsExactly( "2차 카테고리"); + } +} From 5bdcb2a9e737c1f57dc840be9337f185c50b1d34 Mon Sep 17 00:00:00 2001 From: parkjaehak Date: Tue, 4 Feb 2025 15:16:39 +0900 Subject: [PATCH 3/7] =?UTF-8?q?CLAP-221=20Refactor:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/clap/server/TestDataFactory.java | 107 ++++++++++++++++++ .../service/task/ApprovalTaskServiceTest.java | 100 ++++++++++++++++ .../task/FindTasksRequestedByUserTest.java | 72 +++--------- 3 files changed, 225 insertions(+), 54 deletions(-) create mode 100644 src/test/java/clap/server/TestDataFactory.java create mode 100644 src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java diff --git a/src/test/java/clap/server/TestDataFactory.java b/src/test/java/clap/server/TestDataFactory.java new file mode 100644 index 00000000..e433b310 --- /dev/null +++ b/src/test/java/clap/server/TestDataFactory.java @@ -0,0 +1,107 @@ +package clap.server; + +import clap.server.adapter.inbound.web.dto.task.request.FilterTaskListRequest; +import clap.server.adapter.outbound.persistense.entity.member.constant.MemberRole; +import clap.server.adapter.outbound.persistense.entity.member.constant.MemberStatus; +import clap.server.adapter.outbound.persistense.entity.task.constant.LabelColor; +import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; +import clap.server.domain.model.member.Member; +import clap.server.domain.model.member.MemberInfo; +import clap.server.domain.model.task.Category; +import clap.server.domain.model.task.Label; +import clap.server.domain.model.task.Task; +import org.springframework.data.domain.PageImpl; + +import java.time.LocalDateTime; +import java.util.List; + +public class TestDataFactory { + + public static Member createAdmin() { + return new Member(1L, createAdminInfo(), null, + true, true, true, + null, MemberStatus.ACTIVE, "1111"); + } + public static Member createManagerWithReviewer() { + return new Member(2L, createManagerWithReviewerInfo(), createAdmin(), + true, true, true, + null, MemberStatus.ACTIVE, "1111"); + } + public static Member createManager() { + return new Member(3L, createManagerInfo(), createAdmin(), + true, true, true, + null, MemberStatus.ACTIVE, "1111"); + } + public static Member createUser() { + return new Member(4L, createUserInfo(), createAdmin(), + true, true, true, + null, MemberStatus.ACTIVE, "1111"); + } + + public static MemberInfo createAdminInfo(){ + return new MemberInfo("홍길동(관리자)", "atom8426@naver.com", "atom.admin", false, null, MemberRole.ROLE_ADMIN, "인프라"); + } + public static MemberInfo createManagerWithReviewerInfo(){ + return new MemberInfo("홍길동(리뷰어)", "atom8426@naver.com", "atom.manager", true, null, MemberRole.ROLE_MANAGER, "인프라"); + } + public static MemberInfo createManagerInfo(){ + return new MemberInfo("홍길동(매니저)", "atom8426@naver.com", "atom.manager", false, null, MemberRole.ROLE_MANAGER, "인프라"); + } + public static MemberInfo createUserInfo(){ + return new MemberInfo("홍길동(사용자)", "atom8426@naver.com", "atom.user", false, null, MemberRole.ROLE_USER, "인프라"); + } + + public static Category createMainCategory() { + return Category.builder() + .categoryId(1L) + .name("1차 카테고리") + .code("VM") + .isDeleted(false) + .descriptionExample("메인 카테고리 입니다.") + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .build(); + } + + public static Category createCategory(Category mainCategory) { + return Category.builder() + .categoryId(2L) + .name("2차 카테고리") + .code("CR") + .isDeleted(false) + .descriptionExample("서브 카테고리 입니다.") + .mainCategory(mainCategory) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .build(); + } + + public static Task createTask(Long id, String taskCode, String title, TaskStatus taskStatus, Category category, LocalDateTime finishedAt, Member processor) { + return Task.builder() + .taskId(id) + .taskCode(taskCode) + .title(title) + .description(null) + .category(category) + .taskStatus(taskStatus) + .finishedAt(finishedAt) + .processor(processor) + .label(createLabel()) + .build(); + } + + public static Label createLabel() { + return Label.builder() + .labelId(1L) + .admin(null) + .labelName("레이블") + .labelColor(LabelColor.BLUE) + .isDeleted(false) + .build(); + } + + + public static PageImpl createTaskPage(List tasks) { + return new PageImpl<>(tasks); + } +} diff --git a/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java new file mode 100644 index 00000000..7796944e --- /dev/null +++ b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java @@ -0,0 +1,100 @@ +package clap.server.application.service.task; + +import clap.server.adapter.inbound.web.dto.task.request.ApprovalTaskRequest; +import clap.server.adapter.inbound.web.dto.task.response.ApprovalTaskResponse; +import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; +import clap.server.TestDataFactory; +import clap.server.application.port.inbound.domain.CategoryService; +import clap.server.application.port.inbound.domain.LabelService; +import clap.server.application.port.inbound.domain.MemberService; +import clap.server.application.port.inbound.domain.TaskService; +import clap.server.application.port.outbound.taskhistory.CommandTaskHistoryPort; +import clap.server.application.service.webhook.SendNotificationService; +import clap.server.domain.model.member.Member; +import clap.server.domain.model.task.Category; +import clap.server.domain.model.task.Label; +import clap.server.domain.model.task.Task; +import clap.server.domain.model.task.TaskHistory; +import clap.server.domain.policy.task.RequestedTaskUpdatePolicy; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +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 static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + + +@ExtendWith(MockitoExtension.class) +class ApprovalTaskServiceTest { + + @InjectMocks + private ApprovalTaskService approvalTaskService; + + @Mock + private MemberService memberService; + + @Mock + private TaskService taskService; + + @Mock + private CategoryService categoryService; + + @Mock + private LabelService labelService; + + @Mock + private RequestedTaskUpdatePolicy requestedTaskUpdatePolicy; + + @Mock + private CommandTaskHistoryPort commandTaskHistoryPort; + + @Mock + private SendNotificationService sendNotificationService; + + + private Member reviewer, processor; + private Task task; + private Label label; + private Category category, mainCategory; + + @BeforeEach + void setUp() { + reviewer = TestDataFactory.createManagerWithReviewer(); + processor = TestDataFactory.createManager(); + mainCategory = TestDataFactory.createMainCategory(); + category = TestDataFactory.createCategory(mainCategory); + label = TestDataFactory.createLabel(); + task = TestDataFactory.createTask( 1L,"TC001", "제목1", TaskStatus.REQUESTED, category, null, processor); + } + + @Test + @DisplayName("작업 승인 처리") + void approvalTask() { + //given + Long reviewerId = 2L; + Long taskId = 1L; + ApprovalTaskRequest approvalTaskRequest = new ApprovalTaskRequest(2L, 2L, null, null); + + when(memberService.findReviewer(reviewerId)).thenReturn(reviewer); + when(taskService.findById(taskId)).thenReturn(task); + when(memberService.findById(approvalTaskRequest.processorId())).thenReturn(processor); + when(categoryService.findById(approvalTaskRequest.categoryId())).thenReturn(category); + when(labelService.findById(approvalTaskRequest.labelId())).thenReturn(label); + when(taskService.upsert(task)).thenReturn(task); + + //when + ApprovalTaskResponse response = approvalTaskService.approvalTaskByReviewer(reviewerId, taskId, approvalTaskRequest); + + //then + assertThat(response).isNotNull(); + assertThat(response.taskStatus()).isEqualTo(TaskStatus.IN_PROGRESS); + assertThat(response.taskId()).isEqualTo(task.getTaskId()); + verify(requestedTaskUpdatePolicy).validateTaskRequested(task); + verify(commandTaskHistoryPort, times(1)).save(any(TaskHistory.class)); + } +} + diff --git a/src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java b/src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java index 0b1f2525..50cccf6e 100644 --- a/src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java +++ b/src/test/java/clap/server/application/service/task/FindTasksRequestedByUserTest.java @@ -3,8 +3,8 @@ import clap.server.adapter.inbound.web.dto.common.PageResponse; import clap.server.adapter.inbound.web.dto.task.request.FilterTaskListRequest; import clap.server.adapter.inbound.web.dto.task.response.FilterRequestedTasksResponse; -import clap.server.adapter.outbound.persistense.entity.member.constant.MemberStatus; import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; +import clap.server.TestDataFactory; import clap.server.application.port.inbound.domain.MemberService; import clap.server.application.port.outbound.task.LoadTaskPort; import clap.server.domain.model.member.Member; @@ -36,57 +36,18 @@ class FindTasksRequestedByUserTest { private LoadTaskPort loadTaskPort; @InjectMocks private FindTaskListService findTaskListService; - - private FilterTaskListRequest filterTaskListRequest; - private Member member; + private Member user; private Page taskPage; private Task task1, task2; + private Category category, mainCategory; @BeforeEach void setUp() { - member = new Member(1L, null, null, - true, false, true, - null, MemberStatus.ACTIVE, null - ); - Category mainCategory = Category.builder() - .categoryId(1L) - .name("1차 카테고리") - .code("VM") - .isDeleted(false) - .descriptionExample("메인 카테고리 입니다.") - .createdAt(LocalDateTime.now()) - .updatedAt(LocalDateTime.now()) - .build(); - Category category = Category.builder() - .categoryId(2L) - .name("2차 카테고리") - .code("CR") - .isDeleted(false) - .descriptionExample("서브 카테고리 입니다.") - .mainCategory(mainCategory) - .createdAt(LocalDateTime.now()) - .updatedAt(LocalDateTime.now()) - .build(); - task1 = Task.builder() - .taskId(1L) - .taskCode("TC001") - .title("제목1") - .description("설명1") - .category(category) - .taskStatus(TaskStatus.REQUESTED) - .finishedAt(null) - .build(); - task2 = Task.builder() - .taskId(2L) - .taskCode("TC002") - .title("제목2") - .description("설명2") - .category(category) - .taskStatus(TaskStatus.COMPLETED) - .finishedAt(LocalDateTime.of(2025,2,4,11,30,11)) - .build(); - - filterTaskListRequest = new FilterTaskListRequest(null, List.of(), List.of(), "", "", List.of(), "", ""); + user = TestDataFactory.createUser(); + mainCategory = TestDataFactory.createMainCategory(); + category = TestDataFactory.createCategory(mainCategory); + task1 = TestDataFactory.createTask(1L, "TC001", "제목1", TaskStatus.REQUESTED, category,null, null); + task2 = TestDataFactory.createTask(2L, "TC002", "제목2", TaskStatus.COMPLETED, category, LocalDateTime.of(2025, 2, 4, 11, 30, 11), user); taskPage = new PageImpl<>(List.of(task1, task2)); } @@ -94,12 +55,14 @@ void setUp() { @DisplayName("요청한 작업 목록 조회") void findRequestedByUserTasks() { //given + Long userId = 4L; PageRequest pageable = PageRequest.of(0, 20); - when(memberService.findActiveMember(1L)).thenReturn(member); - when(loadTaskPort.findTasksRequestedByUser(1L, pageable, filterTaskListRequest)) + FilterTaskListRequest filterTaskListRequest = new FilterTaskListRequest(null, List.of(), List.of(), "", "", List.of(), "", ""); + when(memberService.findActiveMember(userId)).thenReturn(user); + when(loadTaskPort.findTasksRequestedByUser(userId, pageable, filterTaskListRequest)) .thenReturn(taskPage); //when - PageResponse result = findTaskListService.findTasksRequestedByUser(member.getMemberId(), pageable, filterTaskListRequest); + PageResponse result = findTaskListService.findTasksRequestedByUser(userId, pageable, filterTaskListRequest); //then assertThat(result.content()).hasSize(2) @@ -121,15 +84,16 @@ void findRequestedByUserTasks() { @DisplayName("요청한 작업 목록 조회 - 카테고리 조건") void findRequestedByUserTasks_FilteredWithCategory() { // given + Long userId = 4L; PageRequest pageable = PageRequest.of(0, 20); - filterTaskListRequest = new FilterTaskListRequest(null, List.of(2L), List.of(), "", "", List.of(), "", ""); + FilterTaskListRequest filterTaskListRequest = new FilterTaskListRequest(null, List.of(2L), List.of(), "", "", List.of(), "", ""); taskPage = new PageImpl<>(List.of(task2)); - when(memberService.findActiveMember(1L)).thenReturn(member); - when(loadTaskPort.findTasksRequestedByUser(1L, pageable, filterTaskListRequest)) + when(memberService.findActiveMember(userId)).thenReturn(user); + when(loadTaskPort.findTasksRequestedByUser(user.getMemberId(), pageable, filterTaskListRequest)) .thenReturn(taskPage); // when - PageResponse result = findTaskListService.findTasksRequestedByUser(member.getMemberId(), pageable, filterTaskListRequest); + PageResponse result = findTaskListService.findTasksRequestedByUser(userId, pageable, filterTaskListRequest); // then assertThat(result.content()).hasSize(1); From 3e65439983d09e71f1dfaf6f1b73f11526004faa Mon Sep 17 00:00:00 2001 From: parkjaehak Date: Tue, 4 Feb 2025 15:36:46 +0900 Subject: [PATCH 4/7] =?UTF-8?q?CLAP-221=20Fix:=20=EC=9E=91=EC=97=85=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=20=EC=B2=98=EB=A6=AC=20=EC=8B=9C=20=EB=A7=88?= =?UTF-8?q?=EA=B0=90=EA=B8=B0=ED=95=9C,=20=EB=A0=88=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EB=84=90=20=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clap/server/application/mapper/TaskResponseMapper.java | 2 +- .../server/application/service/task/ApprovalTaskService.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/clap/server/application/mapper/TaskResponseMapper.java b/src/main/java/clap/server/application/mapper/TaskResponseMapper.java index f68a80ef..5c672e59 100644 --- a/src/main/java/clap/server/application/mapper/TaskResponseMapper.java +++ b/src/main/java/clap/server/application/mapper/TaskResponseMapper.java @@ -97,7 +97,7 @@ public static ApprovalTaskResponse toApprovalTaskResponse(Task approvedTask) { approvedTask.getProcessor().getNickname(), approvedTask.getReviewer().getNickname(), approvedTask.getDueDate(), - approvedTask.getLabel().getLabelName(), + approvedTask.getLabel() != null ? approvedTask.getLabel().getLabelName() : "", approvedTask.getTaskStatus() ); } diff --git a/src/main/java/clap/server/application/service/task/ApprovalTaskService.java b/src/main/java/clap/server/application/service/task/ApprovalTaskService.java index 0a033b47..4c50110c 100644 --- a/src/main/java/clap/server/application/service/task/ApprovalTaskService.java +++ b/src/main/java/clap/server/application/service/task/ApprovalTaskService.java @@ -46,7 +46,10 @@ public ApprovalTaskResponse approvalTaskByReviewer(Long reviewerId, Long taskId, Task task = taskService.findById(taskId); Member processor = memberService.findById(approvalTaskRequest.processorId()); Category category = categoryService.findById(approvalTaskRequest.categoryId()); - Label label = labelService.findById(approvalTaskRequest.labelId()); + Label label = null; + if (approvalTaskRequest.labelId() != null) { + label = labelService.findById(approvalTaskRequest.labelId()); + } requestedTaskUpdatePolicy.validateTaskRequested(task); task.approveTask(reviewer, processor, approvalTaskRequest.dueDate(), category, label); From 5bb731fb9aa59ff67bf0cf341ffb94c5b1731628 Mon Sep 17 00:00:00 2001 From: parkjaehak Date: Tue, 4 Feb 2025 15:48:48 +0900 Subject: [PATCH 5/7] =?UTF-8?q?CLAP-221=20Fix:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=8B=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=85=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/task/ApprovalTaskServiceTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java index 7796944e..c3e20952 100644 --- a/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java +++ b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java @@ -58,7 +58,6 @@ class ApprovalTaskServiceTest { private Member reviewer, processor; private Task task; - private Label label; private Category category, mainCategory; @BeforeEach @@ -67,7 +66,6 @@ void setUp() { processor = TestDataFactory.createManager(); mainCategory = TestDataFactory.createMainCategory(); category = TestDataFactory.createCategory(mainCategory); - label = TestDataFactory.createLabel(); task = TestDataFactory.createTask( 1L,"TC001", "제목1", TaskStatus.REQUESTED, category, null, processor); } @@ -83,7 +81,6 @@ void approvalTask() { when(taskService.findById(taskId)).thenReturn(task); when(memberService.findById(approvalTaskRequest.processorId())).thenReturn(processor); when(categoryService.findById(approvalTaskRequest.categoryId())).thenReturn(category); - when(labelService.findById(approvalTaskRequest.labelId())).thenReturn(label); when(taskService.upsert(task)).thenReturn(task); //when From f974c2f8700da67c5ea1e5f0a846edf2cbc3caaf Mon Sep 17 00:00:00 2001 From: parkjaehak Date: Tue, 4 Feb 2025 19:50:02 +0900 Subject: [PATCH 6/7] =?UTF-8?q?CLAP-221=20Fix:=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EB=B6=88=EC=9D=BC=EC=B9=98=20=EC=97=90=EB=9F=AC=20=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/task/ApprovalTaskServiceTest.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java index c3e20952..aeb225cb 100644 --- a/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java +++ b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java @@ -16,6 +16,8 @@ import clap.server.domain.model.task.Task; import clap.server.domain.model.task.TaskHistory; import clap.server.domain.policy.task.RequestedTaskUpdatePolicy; +import clap.server.exception.DomainException; +import clap.server.exception.code.TaskErrorCode; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -25,6 +27,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.*; @@ -45,7 +48,6 @@ class ApprovalTaskServiceTest { @Mock private LabelService labelService; - @Mock private RequestedTaskUpdatePolicy requestedTaskUpdatePolicy; @@ -66,7 +68,7 @@ void setUp() { processor = TestDataFactory.createManager(); mainCategory = TestDataFactory.createMainCategory(); category = TestDataFactory.createCategory(mainCategory); - task = TestDataFactory.createTask( 1L,"TC001", "제목1", TaskStatus.REQUESTED, category, null, processor); + task = TestDataFactory.createTask(1L, "TC001", "제목1", TaskStatus.REQUESTED, category, null, processor); } @Test @@ -88,10 +90,27 @@ void approvalTask() { //then assertThat(response).isNotNull(); - assertThat(response.taskStatus()).isEqualTo(TaskStatus.IN_PROGRESS); assertThat(response.taskId()).isEqualTo(task.getTaskId()); + assertThat(response.taskStatus()).isEqualTo(TaskStatus.IN_PROGRESS); verify(requestedTaskUpdatePolicy).validateTaskRequested(task); - verify(commandTaskHistoryPort, times(1)).save(any(TaskHistory.class)); } -} + @Test + @DisplayName("작업 승인 처리 중 예외 - 상태 불일치") + void approvalTask_throwsDomainException_whenTaskStatusIsNotRequested() { + //given + Long reviewerId = 2L; + Long taskId = 1L; + ApprovalTaskRequest approvalTaskRequest = new ApprovalTaskRequest(2L, 2L, null, null); + task = TestDataFactory.createTask(1L, "TC001", "제목1", TaskStatus.COMPLETED, category, null, processor); + when(taskService.findById(taskId)).thenReturn(task); + + //when + doThrow(new DomainException(TaskErrorCode.TASK_STATUS_MISMATCH)) + .when(requestedTaskUpdatePolicy).validateTaskRequested(task); + //then + assertThatThrownBy(() -> approvalTaskService.approvalTaskByReviewer(reviewerId, taskId, approvalTaskRequest)) + .isInstanceOf(DomainException.class) + .hasMessage(TaskErrorCode.TASK_STATUS_MISMATCH.getMessage()); + } +} From afc70f331da348b57800c8a1a022e9a869055b4e Mon Sep 17 00:00:00 2001 From: parkjaehak Date: Tue, 4 Feb 2025 22:59:36 +0900 Subject: [PATCH 7/7] =?UTF-8?q?CLAP-221=20Add:=20department=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20code=20=EC=86=8D=EC=84=B1=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outbound/persistense/entity/member/DepartmentEntity.java | 3 +++ .../persistense/mapper/DepartmentPersistenceMapper.java | 2 -- src/main/java/clap/server/domain/model/common/BaseTime.java | 2 +- src/main/java/clap/server/domain/model/member/Member.java | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/clap/server/adapter/outbound/persistense/entity/member/DepartmentEntity.java b/src/main/java/clap/server/adapter/outbound/persistense/entity/member/DepartmentEntity.java index 2da65f2b..51dcb08b 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/entity/member/DepartmentEntity.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/entity/member/DepartmentEntity.java @@ -24,6 +24,9 @@ public class DepartmentEntity extends BaseTimeEntity { @JoinColumn(name = "admin_id") private MemberEntity admin; + @Column(nullable = false) + private String code; + @Column(nullable = false) private String name; diff --git a/src/main/java/clap/server/adapter/outbound/persistense/mapper/DepartmentPersistenceMapper.java b/src/main/java/clap/server/adapter/outbound/persistense/mapper/DepartmentPersistenceMapper.java index ac62cfe1..87e6947b 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/mapper/DepartmentPersistenceMapper.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/mapper/DepartmentPersistenceMapper.java @@ -10,10 +10,8 @@ public interface DepartmentPersistenceMapper extends PersistenceMapper { @Mapping(source = "admin.memberId", target = "adminId") - @Mapping(source = "name", target = "code") Department toDomain(DepartmentEntity entity); - @Mapping(source = "code", target = "name") @Mapping(source = "adminId", target = "admin.memberId") DepartmentEntity toEntity(Department domain); } \ No newline at end of file diff --git a/src/main/java/clap/server/domain/model/common/BaseTime.java b/src/main/java/clap/server/domain/model/common/BaseTime.java index 1815c0cb..ccf54ee4 100644 --- a/src/main/java/clap/server/domain/model/common/BaseTime.java +++ b/src/main/java/clap/server/domain/model/common/BaseTime.java @@ -9,7 +9,7 @@ import java.time.LocalDateTime; @Getter -@SuperBuilder(toBuilder = true) +@SuperBuilder @MappedSuperclass @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BaseTime { diff --git a/src/main/java/clap/server/domain/model/member/Member.java b/src/main/java/clap/server/domain/model/member/Member.java index bdffb88b..3c6d7163 100644 --- a/src/main/java/clap/server/domain/model/member/Member.java +++ b/src/main/java/clap/server/domain/model/member/Member.java @@ -10,7 +10,7 @@ import lombok.experimental.SuperBuilder; @Getter -@SuperBuilder(toBuilder = true) +@SuperBuilder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class Member extends BaseTime {