JUnit, TDD , 클린코드 연습

프로젝트 테스트 코드 작성

쭈녁 2024. 4. 27. 23:47

테스트란?

 

  • 단위 테스트(Unit Test): 비즈니스 로직에서 사용되는 메서드를 독립적으로 테스트한다.
  • 슬라이스 테스트: 애플리케이션을 특정 계층의 기능을 Mock 객체를 사용하여 테스트한다.

 

 

코스 최종 프로젝트를 진행 중에 애플리케이션 기능을 테스트하여 더욱 탄탄한 서비스로직을 구현하고자 테스트 코드를 작성해 보았다.

 

최종으로는 통합 테스트까지 진행하면 좋겠지만 단위테스트와 슬라이스 테스트까지 진행하는 것이 목표이다.

 

Mock 객체 세팅 및 기본 셋업 

@ExtendWith(MockitoExtension.class)
class HeartReviewServiceImplTest {
    @Mock
    private HeartReviewRepository heartReviewRepository;
    @Mock
    private ReviewRepository reviewRepository;
    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private HeartReviewServiceImpl heartReviewService;

    private Long heartReviewId;
    private User user;
    private Review review;

    @BeforeEach
    void setUp() {
        heartReviewId = 1000L;

        user = User.builder().userId(2000L).username("testUsername").build();
        review = Review.builder().id(3000L).title("testTitle").heartCount(0).build();
    }
 }

 

1. 좋아요 성공 케이스

@Test
@DisplayName("(성공) : 좋아요")
    public void SaveSuccess() throws Exception {
    //given : beforeEach 상황

    //when
    // 1. 좋아요 누르지 않은 상황
    when(heartReviewRepository.existsByUserUserIdAndReviewId(user.getUserId(), review.getId())).thenReturn(false);

    //2. 리뷰Id로 찾으면 위에 만든 리뷰가 나와야 함
    when(reviewRepository.findById(review.getId())).thenReturn(Optional.ofNullable(review));

    //3. userId 찾으면 위에 만든 유저가 나와야 함
    when(userRepository.findById(user.getUserId())).thenReturn(Optional.ofNullable(user));

    //4. 좋아요 save 했을때 상황
    when(heartReviewRepository.save(any(HeartReview.class))).thenReturn(HeartReview.builder().id(heartReviewId).user(user).review(review).build());

    Long save = heartReviewService.save(user.getUserId(), review.getId());

    //then
    assertThat(save).isEqualTo(heartReviewId);
}

 

2. 좋아요 실패 케이스 (이미 누른 상태)

@Test
@DisplayName("(실패) : 좋아요 이미 눌른 상태에서 다시 좋아요")
public void SaveFailAtExist() throws Exception {
    //given : beforeEach 상황
    HeartReview heart = HeartReview.builder().id(heartReviewId).review(review).user(user).build();

    //when
    // 1. 좋아요 이미 누른 상황
    when(heartReviewRepository.existsByUserUserIdAndReviewId(heart.getUser().getUserId(), heart.getReview().getId())).thenReturn(true);

    //then
    assertThatThrownBy(() -> heartReviewService.save(user.getUserId(), review.getId())).isInstanceOf(IllegalArgumentException.class).hasMessage("이미 좋아요 클릭한 후기입니다.");
}

 

3. 좋아요 취소 성공

@Test
@DisplayName("(성공) : 좋아요 취소")
public void deleteSuccess() throws Exception {
    //given : beforeEach 상황
    HeartReview heart = HeartReview.builder().id(heartReviewId).review(review).user(user).build();
    review.addHeartCount();

    //when
    // 1. 좋아요 누른 상황
    when(heartReviewRepository.existsByUserUserIdAndReviewId(user.getUserId(), review.getId())).thenReturn(true);

    //2. 리뷰Id로 찾으면 위에 만든 리뷰가 나와야 함
    when(reviewRepository.findById(review.getId())).thenReturn(Optional.ofNullable(review));

    //3. userId 가 누른 Heart 찾는 상황
    when(heartReviewRepository.findByUserUserIdAndReviewId(user.getUserId(), review.getId())).thenReturn(Optional.ofNullable(heart));

    //4. 좋아요 save 했을때 상황

    Long delete = heartReviewService.delete(user.getUserId(), review.getId());

    //then
    assertThat(delete).isEqualTo(heartReviewId);
}

 

4. 좋아요 삭제 실패케이스 (좋아요를 누르지 않은 상태)

@Test
@DisplayName("(실패) : 좋아요 누르지 않고 삭제")
public void deleteFailNotExist() throws Exception {
    //given : beforeEach 상황

    //when
    // 1. 좋아요 누르지 않은 상황
    when(heartReviewRepository.existsByUserUserIdAndReviewId(user.getUserId(), review.getId())).thenReturn(false);

    //then
    assertThatThrownBy(() -> heartReviewService.delete(user.getUserId(), review.getId())).isInstanceOf(IllegalArgumentException.class).hasMessage("좋아요 클릭 되지 않은 후기입니다.");
}

 

5. 좋아요 실패케이스 (없는 리뷰에 좋아요)

@Test
@DisplayName("(실패) : 좋아요 누를 때 리뷰가 없음")
public void saveFailReviewNotFound() throws Exception {
    //given : beforeEach 상황

    //when
    // 1. 좋아요 누르지 않은 상황
    when(heartReviewRepository.existsByUserUserIdAndReviewId(user.getUserId(), review.getId())).thenReturn(false);

    //2. 리뷰Id로 찾으면 위에 만든 리뷰가 나와야 함
    when(reviewRepository.findById(review.getId())).thenReturn(Optional.ofNullable(null));

    //then
    assertThatThrownBy(() -> heartReviewService.save(user.getUserId(), review.getId())).isInstanceOf(CustomException.class).hasMessage(ErrorCode.REVIEW_NOT_FOUND.getMessage());
}

 

6. 좋아요 실패케이스 (유저의 정보가 잘못됨)

@Test
@DisplayName("(실패) : 유저정보가 잘못됨")
public void saveFailUserNotFound() throws Exception {
    //given : beforeEach 상황

    //when
    // 1. 좋아요 누르지 않은 상황
    when(heartReviewRepository.existsByUserUserIdAndReviewId(user.getUserId(), review.getId())).thenReturn(false);

    //2. 리뷰Id로 찾으면 위에 만든 리뷰가 나와야 함
    when(reviewRepository.findById(review.getId())).thenReturn(Optional.ofNullable(review));

    //3. userId 찾으면 위에 만든 유저가 나와야 함
    when(userRepository.findById(user.getUserId())).thenReturn(Optional.ofNullable(null));

    //then
    assertThatThrownBy(() -> heartReviewService.save(user.getUserId(), review.getId())).isInstanceOf(CustomException.class).hasMessage(ErrorCode.USER_NOT_FOUND.getMessage());
}

 

7. 좋아요 DB 조회 성공 케이스

@Test
@DisplayName("(성공) : 좋아요 여부 확인 테스트")
public void checkHeart() throws Exception {
    //given : 이미 좋아요 누른 상태
    HeartReview heart = HeartReview.builder().id(heartReviewId).review(review).user(user).build();
    //when
    when(heartReviewRepository.existsByUserUserIdAndReviewId(heart.getUser().getUserId(), heart.getReview().getId())).thenReturn(true);
    //then
    Boolean result = heartReviewService.checkReviewHeart(user.getUserId(), review.getId());

    assertThat(result).isEqualTo(true);
}