inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

댓글 최대 2 depth - CUD API 구현

CommentServiceTest에서 테스트 오류가 나요.

해결된 질문

279

유지상

작성한 질문수 1

0

 

[문의사항]

강사님의 코드 그대로 따라서 하나하나 작성하고, 모든 부분의 설정을 똑같이 했습니다.
Comment 테스트 중에 <삭제할 댓글이 자식 있으면, 삭제 표시만 한다.> 는 성공이 되었습니다.

그러나 <하위 댓글이 삭제되고, 삭제되지 않은 부모면, 하위 댓글만 삭제한다.> 부분의 테스트를 그대로 따라했는데, mockito.exceptions.misusing.UnnecssaryStubbingException 오류가 납니다.

강의 자료로 올려주신 소스코드를 그대로 복사하여 붙여넣기 해도 같은 오류가 납니다.

소스코드와 에러메세지 작성드리며, 같은 환경에서 똑같은 소스코드를 작성했는데 어떻게 오류가 나는지 궁금합니다. 해결 부탁드립니다 ㅠㅠㅠ

package kuke.board.comment.service;

import kuke.board.comment.entity.Comment;
import kuke.board.comment.repository.CommentRepository;
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 java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class CommentServiceTest {
    @InjectMocks
    CommentService commentService;
    @Mock
    CommentRepository commentRepository;

    @Test
    @DisplayName("삭제할 댓글이 자식 있으면, 삭제 표시만 한다.")
    void deleteShouldMarkDeletedIfHasChildren() {
        // given
        Long articleId = 1L;
        Long commentId = 2L;
        Comment comment = createComment(articleId, commentId);
        given(commentRepository.findById(commentId))
                .willReturn(Optional.of(comment));
        given(commentRepository.countBy(articleId, commentId, 2L)).willReturn(2L);

        // when
        commentService.delete(commentId);

        // then
        verify(comment).delete();
    }

    @Test
    @DisplayName("하위 댓글이 삭제되고, 삭제되지 않은 부모면, 하위 댓글만 삭제한다.")
    void deleteShouldDeleteChildOnlyIfNotDeletedParent() {
        // given
        Long articleId = 1L;
        Long commentId = 2L;
        Long parentCommentId = 1L;

        Comment comment = createComment(articleId, commentId, parentCommentId);
        given(comment.isRoot()).willReturn(false);

        Comment parentComment = mock(Comment.class);
        given(parentComment.getDeleted()).willReturn(false);

        given(commentRepository.findById(commentId))
                .willReturn(Optional.of(comment));
        given(commentRepository.countBy(articleId, commentId, 2L)).willReturn(1L);

        given(commentRepository.findById(parentCommentId))
                .willReturn(Optional.of(parentComment));

        // when
        commentService.delete(commentId);

        // then
        verify(commentRepository).delete(comment);
        verify(commentRepository, never()).delete(parentComment);
    }

    private Comment createComment(Long articleId, Long commentId) {
        Comment comment = mock(Comment.class);
        given(comment.getArticleId()).willReturn(articleId);
        given(comment.getCommentId()).willReturn(commentId);
        return comment;
    }

    private Comment createComment(Long articleId, Long commentId, Long parentCommentId) {
        Comment comment = createComment(articleId, commentId);
        given(comment.getParentCommentId()).willReturn(parentCommentId);
        return comment;
    }
}
image.png

 

 

java mysql spring-boot kafka redis

답변 4

0

유지상

CommentService 파일과 CommentServiceTest 파일 모두 복붙해서 진행해도 해결이 안되어서, 두개의 파일 모두 삭제하고 다시 복붙해서 넣으니까 해결되었습니다!

감사합니다!

0

쿠케

잘 해결되어서 다행이네요!

무언가 코드가 잘못 입력된 부분이 있었을지 싶습니다.

저번에 다른 분 문의에서 CommentService countChildren 메소드에서 getParentCommentId가 아니라 getCommentId를 잘못 호출하시던 케이스가 있었어서, 아마 이러한 실수였을지 싶네요!

에러 나는 지점이 위 상황이랑 유사하군요..!

0

쿠케

지상님, 안녕하세요!

해당 에러는 given(XXX).willReturn(XXX)으로 정의한 내용이 실제 코드에서 수행되지 않을 때 발생할 수 있습니다.

CommentService에서 코드가 잘못된 지점이 있었을지 싶네요!

에러가 발생한 부분이 본 소스코드에서 정상적으로 수행될 수 있는 코드일지 확인해보시면 좋을 것 같습니다!

해결하기 어려우시면, CommentService 코드도 복사해서 넣어보시거나 현재 소스코드 복사해서 올려주시겠어요?

0

유지상

strictness 설정으로 해결하였습니다.

그러나 강사님과 같은 개발환경으로 버전까지 똑같이해서 작성하는데 왜 차이가 나는지 알고싶어요.

 

추가로, 3번째 테스트 <하위 댓글이 삭제되고, 삭제된 부모면, 재귀적으로 모두 삭제한다.>에도 오류가 납니다.

@Test
@DisplayName("하위 댓글이 삭제되고, 삭제된 부모면, 재귀적으로 모두 삭제한다.")
void deleteShouldDeleteAllRecursivelyIfDeleteParent() {
    // given
    Long articleId = 1L;
    Long commentId = 2L;
    Long parentCommentId = 1L;

    Comment comment = createComment(articleId, commentId, parentCommentId);
    given(comment.isRoot()).willReturn(false);

    Comment parentComment = createComment(articleId, parentCommentId);
    given(parentComment.isRoot()).willReturn(true);
    given(parentComment.getDeleted()).willReturn(true);

    given(commentRepository.findById(commentId))
            .willReturn(Optional.of(comment));
    given(commentRepository.countBy(articleId, commentId, 2L)).willReturn(1L);

    given(commentRepository.findById(parentCommentId))
            .willReturn(Optional.of(parentComment));
    given(commentRepository.countBy(articleId, parentCommentId, 2L)).willReturn(1L);

    // when
    commentService.delete(commentId);

    // then
    verify(commentRepository).delete(comment);
    verify(commentRepository).delete(parentComment);
}
image.png

 

0

쿠케

strictness 설정을 바꾸면 UnnecssaryStubbingException 부분은 해결될 수 있으나,

mock 객체에 대해 정의한 코드가 수행되지 않은 상황이라 올바른 해결책이 아닐 수 있습니다!

given에 정의한 내용이 본 소스코드에서 왜 호출되지 않는지 디버깅해보시는걸 추천드립니다!

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. 유지상님.

질문해 주신 UnnecessaryStubbingException은 Mockito의 엄격 모드에서 발생하는 오류로, 설정된 스텁이 실제로 사용되지 않았을 때 나타납니다. 이 오류는 코드에서 사용하지 않는 Stubbing을 포함하고 있을 때 주로 발생합니다.

오류 해결 방향

  1. Unnecessary Stubbing 제거:

    • UnnecessaryStubbingException은 Mock 객체의 특정 메서드를 설정했으나, 실제로 테스트 코드에서 그 메서드가 호출되지 않을 때 발생합니다. 예를 들어, given(comment.isRoot()).willReturn(false); 와 같은 부분이 실제 테스트 실행 시에 호출되지 않았다면 이로 인해 오류가 발생할 수 있습니다.
  2. Strictness 설정 조정:

    • 귀하의 코드가 자체적으로 문제가 없다면, Mockito의 Strictness 설정을 조정하여 해결할 수 있습니다. 예를 들면, lenient() 메소드를 사용하여 좀 더 너그럽게 설정할 수 있습니다:
     @ExtendWith(MockitoExtension.class)
     @MockitoSettings(strictness = Strictness.LENIENT)
     class CommentServiceTest {
         // 테스트 코드...
     }
    
  3. Stubbing 코드 재검토:

    • deleteShouldDeleteChildOnlyIfNotDeletedParent 메소드의 stubbing 설정을 다시 한번 검토해보세요. 특정 메서드가 실제로 사용되었는지를 코드 흐름에서 다시 확인해 보기를 권장드립니다.

유사 질문 및 링크

비슷한 질문과 해결 방법에 대한 추가 정보를 제공할 수 있는 기존 질문 링크를 소개드립니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크와 설명을 제공드립니다. 현재 베타 기능이라 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

@Version 어노테이션이 붙은 필드는 낙관적 락이든 비관적 락이든 업데이트가 됩니다.

0

31

1

consumer에서 에러가 발생할 경우 데이터 유실 문의

0

49

2

게시글 테스트 데이터 삽입

0

51

2

정렬, 필터, 검색 등의 조건이 붙을 경우 최적화할 수 있는 방법이 무엇이 있을까요?

0

104

2

좋아요 기능 정합성 보장 방법

0

98

2

좋아요 동시성처리 최적의 선택?

1

137

2

프론트엔드 msa 환경 api 주소 통합? 과 서버끼리 통신 방식에대해

0

92

2

안녕하세요 무한스크롤 강의듣다가 질문이 있습니다.

0

61

1

조회수 조회 로직 질문

1

67

2

비로그인 유저도 어뷰징 방지 정책

1

73

2

CommentServiceTest의 테스트 로직 질문

0

54

2

무한 스크롤 방식에서 페이지 번호 방식 쿼리의 문제점 의문

1

74

2

path 쿼리 관련 질문드립니다!

0

60

2

antigravity 에디터를 쓰신다면 종료해주세요

1

123

0

프로젝트 구조

0

88

2

article_like_count api test

0

79

2

이벤트 페이로드 객체의 생성 방식이 팩토리 메서드 패턴이 아닌 빌더 패턴인 이유가 궁금합니다!.

0

104

2

[33. 좋아요 수 구현] 에서 테스트 하는 화면 동시성 문제

0

92

2

findByPath에서 articleId로도 검색을 해야 할 것 같아요.

0

94

3

jpa ddl-auto none을 하는 이유와 join 방법

0

97

2

팩터리 메소드와 response 객체 사용 이유가 궁금합니다!

0

91

2

커서 기반 페이지네이션 과 무한 스크롤링

0

111

2

게시글 생성 로직에서 오류 발생시 redis 게시글 수 되돌리기

0

97

2

멀티 모듈이 아닌 MSA 환경에서 common

0

158

2