본문 바로가기
Project/깃터디 (gitudy)

[깃터디/Todo] Todo 삭제 api 구현

by J-rain 2024. 5. 11.

 

💡 .java를 클릭시 관련 커밋으로 이동💡

 회고 

@Repository
public interface StudyTodoMappingRepository extends JpaRepository<StudyTodoMapping, Long> {
    List<StudyTodoMapping> findByUserId(Long userId);
    Optional<StudyTodoMapping> deleteByTodoId(Long todoId);

    List<StudyTodoMapping> findByTodoId(Long todoId);
}

@Repository 는 스프링 프레임워크에서 제공하는 어노테이션으로 해당 클래스가 데이터 저장소, 즉 레포지토리의 역할을 수행한다. @Repository 어노테이션을 통해 스프링의 데이터 접근 계층에 속하는 컴포넌트임을 명시적으로 선언하고 스프링 컨테이너는 이를 통해 해당 클래스를 자동으로 검색하고 빈(bean)으로 등록해준다!!

또한 위의 코드를 보면 JpaRepository를 상속받고있는데 JpaRepository는 스프링 데이터 JPA가 제공하는 인터페이스로, 엔티티에 대한 CRUD(Create, Read, Update, Delete) 작업을 추상화한 메서드를 제공한다. 따라서 기본적인 데이터 접근 기능을 사용할 수 있고 필요에 따라 작성하여 추가적인 데이터 접근 메서를 정의할 수 있는것이다!!! 🤓

 

 

StudyTodoController.java

    // Todo 삭제
    @ApiResponse(responseCode = "200", description = "Todo 삭제 성공")
    @DeleteMapping("/{studyInfoId}/todo/{todoId}")
    public JsonResult<?> deleteStudyTodo(@AuthenticationPrincipal User user,
                                         @PathVariable(name = "studyInfoId") Long studyInfoId,
                                         @PathVariable(name = "todoId") Long todoId) {

        studyMemberService.isValidateStudyLeader(user, studyInfoId);

        studyTodoService.deleteStudyTodo(todoId, studyInfoId);

        return JsonResult.successOf("Todo delete Success");
    }

Todo 삭제도 스터디장만 가능하도록 구현 (스터디장 아닐시 예외반환)

 

 

StudyTodoService.java

    // Todo 삭제
    @Transactional
    public void deleteStudyTodo(Long todoId, Long studyInfoId) {

        // 스터디와 관련된 StudyTodo 조회
        StudyTodo studyTodo = studyTodoRepository.findByIdAndStudyInfoId(todoId, studyInfoId).orElseThrow(() -> {
            log.warn(">>>> {} : {} <<<<", todoId, ExceptionMessage.TODO_NOT_FOUND);
            return new TodoException(ExceptionMessage.TODO_NOT_FOUND);
        });

        // StudyTodoMapping 테이블에서 todoId로 연결된 레코드 삭제
        studyTodoMappingRepository.deleteByTodoId(studyTodo.getId());

        // StudyTodo 테이블에서 해당 todoId에 해당하는 레코드 삭제
        studyTodoRepository.delete(studyTodo);

    }

Todo 삭제 Service 구현


테스트

 

StudyTodoControllerTest.java

    @Test
    public void Todo_삭제_테스트() throws Exception {
        //given
        User savedUser = userRepository.save(generateAuthUser());
        Map<String, String> map = TokenUtil.createTokenMap(savedUser);
        String accessToken = jwtService.generateAccessToken(map, savedUser);
        String refreshToken = jwtService.generateRefreshToken(map, savedUser);

        StudyInfo studyInfo = StudyInfoFixture.createDefaultPublicStudyInfo(savedUser.getId());
        studyInfoRepository.save(studyInfo);

        StudyTodo studyTodo = StudyTodoFixture.createStudyTodo(studyInfo.getId());
        studyTodoRepository.save(studyTodo);

        //when
        doNothing().when(studyMemberService).isValidateStudyLeader(any(User.class), any(Long.class));
        doNothing().when(studyTodoService).deleteStudyTodo(any(Long.class), any(Long.class));

        //then
        mockMvc.perform(delete("/study/" + studyInfo.getId() + "/todo/" + studyTodo.getId())
                        .contentType(MediaType.APPLICATION_JSON)
                        .header(AUTHORIZATION, createAuthorizationHeader(accessToken, refreshToken)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.res_code").value(200))
                .andExpect(jsonPath("$.res_msg").value("OK"))
                .andExpect(jsonPath("$.res_obj").value("Todo delete Success"))
                .andDo(print());
    }

컨트롤러 동작 검증 테스트

 

 

StudyTodoServiceTest.java

    @Test
    @DisplayName("Todo 삭제 테스트")
    void deleteTodo_Success() {
        // given
        User leader = userRepository.save(generateAuthUser());
        User activeMember1 = userRepository.save(generateGoogleUser());
        User activeMember2 = userRepository.save(generateKaKaoUser());

        StudyInfo studyInfo = StudyInfoFixture.createDefaultPublicStudyInfo(leader.getId());
        studyInfoRepository.save(studyInfo);

        studyMemberRepository.saveAll(List.of(
                StudyMemberFixture.createStudyMemberLeader(leader.getId(), studyInfo.getId()),
                StudyMemberFixture.createDefaultStudyMember(activeMember1.getId(), studyInfo.getId()),
                StudyMemberFixture.createDefaultStudyMember(activeMember2.getId(), studyInfo.getId())

        ));
        // 스터디장 To do 생성
        StudyTodo studyTodo = StudyTodoFixture.createStudyTodo(studyInfo.getId());
        studyTodoRepository.save(studyTodo);

        // 활동중인 스터디원들에게 To do 매핑
        studyTodoMappingRepository.saveAll(List.of(
                StudyTodoFixture.createStudyTodoMapping(studyTodo.getId(), activeMember1.getId()),
                StudyTodoFixture.createStudyTodoMapping(studyTodo.getId(), activeMember2.getId())
        ));

        // when
        studyMemberService.isValidateStudyLeader(leader, studyInfo.getId());
        studyTodoService.deleteStudyTodo(studyTodo.getId(), studyInfo.getId());  //To do 삭제

        // then
        assertThrows(TodoException.class, () -> {
            studyTodoService.deleteStudyTodo(990927L, studyInfo.getId());
        }, "TODO_NOT_FOUND 예외가 발생해야 한다.");

        // 등록된 To do는 삭제, 모든 매핑제거
        assertFalse(studyTodoRepository.existsById(studyTodo.getId()));
        List<StudyTodoMapping> todoMappings = studyTodoMappingRepository.findByTodoId(studyTodo.getId());
        assertTrue(todoMappings.isEmpty());

    }

Todo 삭제 Service테스트

댓글