Skip to content

Conversation

@HoyeongJeon
Copy link
Collaborator

@HoyeongJeon HoyeongJeon commented Jun 9, 2025

✅ PR 유형

어떤 변경 사항이 있었나요?

  • 새로운 기능 추가
  • 버그 수정
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

📝 작업 내용

  • Comment 도메인 테스트 작성
  • Kotest 의존성 추가

✏️ 관련 이슈


🎸 기타 사항 or 추가 코멘트

  • 실패 케이스에 대한 테스트 작성 방법 변경

Summary by CodeRabbit

  • 버그 수정

    • 댓글 관련 서비스에서 댓글 조회 메서드가 ID 기반으로 변경되어 조회 방식이 개선되었습니다.
  • 테스트

    • 테스트 코드가 MockK 및 Kotest로 리팩터링되어 테스트 신뢰성과 가독성이 향상되었습니다.
    • 댓글 및 일정 서비스 테스트가 세분화되고 예외 상황에 대한 검증이 추가되었습니다.
    • 댓글 삭제 시 권한 및 일치 여부에 대한 예외 처리 테스트가 보강되었습니다.
  • 기타

    • 일부 내부 속성의 접근 제한자가 변경되었습니다.
    • 빌드 설정에 Kotest 테스트 라이브러리 의존성이 추가되었습니다.

@HoyeongJeon HoyeongJeon self-assigned this Jun 9, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 9, 2025

"""

Walkthrough

이 변경 사항은 테스트 코드에서 Mockito를 MockK로 전환하고, Kotest를 테스트 프레임워크로 도입하며, CommentService의 메서드 시그니처를 ID 기반으로 리팩토링합니다. 또한 SpringContextHolder의 context 프로퍼티를 외부에서 접근 가능하도록 변경하였고, 테스트 코드의 구조와 커버리지를 확장했습니다.

Changes

파일/그룹 변경 요약
build.gradle.kts Kotest 버전 변수 추가 및 Kotest 관련 테스트 의존성 2개 추가
.../core/common/support/SpringContextHolder.kt context 프로퍼티의 접근 제한자를 private에서 public으로 변경
.../schedule/domain/service/CommentService.kt findAllByLetter 메서드를 findAllByLetterId(Long)로 시그니처 및 구현 변경
.../schedule/facade/ReadLetterFacade.kt CommentService 호출을 letter 객체 전달에서 letter.id 전달로 변경
.../schedule/domain/facade/UpsertAndDeleteCommentFacadeTest.kt Mockito → MockK로 전환, 테스트 구조 개선, 삭제 관련 예외 케이스 테스트 추가
.../schedule/domain/service/CommentServiceTest.kt Mockito → MockK로 전환, Kotest 도입, CRUD 및 예외 케이스 테스트 추가, 테스트 구조 세분화
.../schedule/domain/service/ScheduleServiceTest.kt Mockito → MockK로 전환, Kotest 도입, 서비스 인스턴스 생성 방식 변경 및 예외 테스트 개선

Sequence Diagram(s)

sequenceDiagram
    participant Facade as ReadLetterFacade
    participant Service as CommentService
    participant Repo as CommentRepository

    Facade->>Service: findAllByLetterId(letter.id)
    Service->>Repo: findAllByLetterId(letter.id)
    Repo-->>Service: List<Comment>
    Service-->>Facade: List<Comment>
Loading

Possibly related PRs

  • Issue: (#31) 편지 및 댓글 CUD #32: CommentService 클래스 및 관련 메서드(upsert, getById, delete) 도입과 관련된 변경으로, 본 PR의 CommentService 시그니처 리팩토링과 직접적으로 연결됩니다.

Suggested reviewers

  • kimyeoungrok

Poem

🐇
MockK와 Kotest로 점프를 해,
테스트 토끼가 신나게 뛰네!
CommentService는 ID로 말해,
context도 이제 밖에서 보이네.
코드의 숲은 더 단단해졌지,
토끼는 오늘도 코드를 믿지!
🥕
"""


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 718b9c6 and b7a8119.

📒 Files selected for processing (1)
  • src/test/kotlin/gomushin/backend/schedule/domain/service/CommentServiceTest.kt (1 hunks)
🔇 Additional comments (3)
src/test/kotlin/gomushin/backend/schedule/domain/service/CommentServiceTest.kt (3)

40-45: Spring 컨텍스트 모킹 설정이 적절합니다.

SpringContextHolder를 모킹하여 환경별 로직을 지원하는 설정이 잘 구현되어 있습니다. 이는 다른 테스트 클래스들과 일관된 패턴을 따르고 있습니다.


47-92: UpsertTest 클래스의 테스트 케이스들이 잘 구성되어 있습니다.

  • ID가 null인 경우의 생성 테스트와 권한 불일치 시의 예외 테스트가 적절히 분리되어 있습니다.
  • MockK를 사용한 stubbing과 verification이 올바르게 구현되었습니다.
  • 예외 메시지 검증까지 포함하여 테스트 커버리지가 우수합니다.

186-215: DeleteTest 클래스가 잘 구현되어 있습니다.

개별 댓글 삭제와 편지별 댓글 일괄 삭제 기능에 대한 테스트가 명확하게 분리되어 있고, repository 메서드 호출을 적절히 검증하고 있습니다.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (1)
src/test/kotlin/gomushin/backend/schedule/domain/service/ScheduleServiceTest.kt (1)

66-66: ⚠️ Potential issue

잘못된 verification 호출을 수정하세요.

현재 scheduleService.save(any())를 verify하고 있는데, 이는 테스트 대상인 서비스 자체의 메서드를 검증하는 것입니다. 단위 테스트에서는 의존성 호출을 검증해야 합니다.

다음과 같이 수정하세요:

- verify { scheduleService.save(any()) }
+ verify { scheduleRepository.save(any()) }
🧹 Nitpick comments (2)
src/main/kotlin/gomushin/backend/core/common/support/SpringContextHolder.kt (1)

9-9: 캡슐화를 고려한 대안 접근 방법 검토 필요

context 프로퍼티의 가시성을 public으로 변경하는 것은 테스트 목적으로는 유용하지만, 캡슐화 원칙을 위반합니다.

다음과 같은 대안을 고려해보세요:

  • 테스트용 별도 설정 메서드 제공
  • 테스트 전용 인터페이스 분리
  • @TestOnly 어노테이션 추가

현재 변경사항이 테스트 요구사항에 맞다면 최소한 문서화를 통해 의도를 명확히 하세요:

+/**
+ * ApplicationContext instance.
+ * Note: Public visibility is required for test mocking purposes.
+ */
 lateinit var context: ApplicationContext
src/test/kotlin/gomushin/backend/schedule/domain/service/ScheduleServiceTest.kt (1)

45-49: SpringContextHolder 설정 패턴의 중복을 개선할 수 있습니다.

동일한 SpringContextHolder 설정 코드가 여러 테스트 클래스에서 반복되고 있습니다. 공통 base 클래스나 utility 함수로 추출하는 것을 고려해보세요.

예시:

abstract class BaseServiceTest {
    @MockK(relaxed = true)
    protected lateinit var mockAppEnv: AppEnv
    
    @MockK
    protected lateinit var mockApplicationContext: ApplicationContext
    
    @BeforeEach
    fun baseSetup() {
        SpringContextHolder.context = mockApplicationContext
        every { mockApplicationContext.getBean(AppEnv::class.java) } returns mockAppEnv
        every { mockAppEnv.getId() } returns "test-env"
    }
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52bdf38 and 718b9c6.

📒 Files selected for processing (7)
  • build.gradle.kts (2 hunks)
  • src/main/kotlin/gomushin/backend/core/common/support/SpringContextHolder.kt (1 hunks)
  • src/main/kotlin/gomushin/backend/schedule/domain/service/CommentService.kt (1 hunks)
  • src/main/kotlin/gomushin/backend/schedule/facade/ReadLetterFacade.kt (1 hunks)
  • src/test/kotlin/gomushin/backend/schedule/domain/facade/UpsertAndDeleteCommentFacadeTest.kt (2 hunks)
  • src/test/kotlin/gomushin/backend/schedule/domain/service/CommentServiceTest.kt (1 hunks)
  • src/test/kotlin/gomushin/backend/schedule/domain/service/ScheduleServiceTest.kt (2 hunks)
🔇 Additional comments (13)
src/main/kotlin/gomushin/backend/schedule/domain/service/CommentService.kt (2)

42-44: 훌륭한 리팩토링입니다!

메서드 시그니처를 Letter 객체에서 Long ID로 변경한 것은 다음과 같은 이점을 제공합니다:

  • 결합도 감소: 전체 Letter 객체 대신 필요한 ID만 전달
  • 성능 향상: 불필요한 객체 데이터 전달 제거
  • 의도 명확화: 실제로 필요한 데이터가 무엇인지 명시

42-44: 메서드 시그니처 리팩토링이 잘 되었습니다.

findAllByLetter에서 findAllByLetterId로 메서드명을 변경하고 파라미터를 Letter 객체에서 Long ID로 단순화한 것은 좋은 리팩토링입니다. 이를 통해:

  • Comment와 Letter 엔티티 간의 결합도가 감소
  • API가 더 명확하고 간단해짐
  • 불필요한 객체 전달을 피해 성능 개선

ReadLetterFacade에서도 호출 부분이 적절히 업데이트된 것을 확인했습니다.

build.gradle.kts (1)

15-15: Kotest 의존성 추가가 적절합니다

테스트 프레임워크 현대화를 위한 Kotest 의존성 추가가 잘 되었습니다:

  • 버전 5.5.4는 안정적인 버전입니다
  • 필요한 핵심 의존성(runner, assertions)이 모두 포함되었습니다
  • 기존 mockkVersion 패턴과 일관성 있게 버전 변수를 사용했습니다

Also applies to: 94-95

src/main/kotlin/gomushin/backend/schedule/facade/ReadLetterFacade.kt (2)

63-63: CommentService 리팩토링과 일치하는 올바른 업데이트

commentService.findAllByLetterId(letter.id) 호출로 변경한 것이 서비스 레이어의 메서드 시그니처 변경과 완벽하게 일치합니다. 기능적으로 동일하면서 더 효율적인 구현입니다.


63-63: 서비스 메서드 변경에 맞춘 호출 부분 업데이트가 정확합니다.

CommentService의 메서드 시그니처 변경에 맞춰 findAllByLetter(letter)에서 findAllByLetterId(letter.id)로 호출을 변경한 것이 적절합니다. 기능적으로는 동일하면서도 리팩토링된 서비스 API를 올바르게 사용하고 있습니다.

src/test/kotlin/gomushin/backend/schedule/domain/service/ScheduleServiceTest.kt (1)

9-26: MockK와 Kotest 마이그레이션이 잘 적용되었습니다.

Mockito에서 MockK로, JUnit assertion에서 Kotest assertion으로의 전환이 일관성 있게 잘 적용되었습니다.

src/test/kotlin/gomushin/backend/schedule/domain/service/CommentServiceTest.kt (2)

47-92: 테스트 구조화가 잘 되어있습니다.

UpsertTest 중첩 클래스로 생성과 수정 관련 테스트들이 잘 그룹화되어 있고, 각 테스트의 목적이 명확합니다.


94-170: 포괄적인 읽기 테스트 커버리지가 좋습니다.

getById, findById, findAllByLetterId 메서드들에 대한 성공/실패 케이스가 모두 잘 커버되어 있습니다.

src/test/kotlin/gomushin/backend/schedule/domain/facade/UpsertAndDeleteCommentFacadeTest.kt (4)

30-56: MockK 마이그레이션과 설정이 잘 적용되었습니다.

Mockito에서 MockK로의 전환이 깔끔하게 이루어졌고, SpringContextHolder 설정도 적절합니다.


87-175: 삭제 테스트 커버리지가 우수합니다.

DeleteTest 중첩 클래스로 삭제 관련 테스트들이 잘 그룹화되어 있고, 성공 케이스와 함께 권한 검증, 데이터 일관성 검증 등의 에러 케이스들도 모두 잘 커버되어 있습니다.


118-145: 예외 메시지 검증이 정확합니다.

권한 오류 상황에서의 예외 메시지 검증이 정확하게 이루어지고 있습니다. Kotest의 shouldThrowshouldBe 사용도 적절합니다.


147-174: 데이터 일관성 검증 테스트가 잘 작성되었습니다.

댓글의 letterId와 입력받은 letterId 불일치에 대한 검증 로직이 잘 테스트되어 있습니다. 이런 엣지 케이스들을 테스트하는 것은 매우 중요합니다.

src/main/kotlin/gomushin/backend/core/common/support/SpringContextHolder.kt (1)

9-9: 테스트를 위한 가시성 변경이 적절합니다.

context 프로퍼티의 가시성을 변경하여 테스트 클래스에서 ApplicationContext를 모킹할 수 있도록 한 것은 Kotest 프레임워크 도입과 테스트 코드 작성 목표에 부합합니다. 다만 캡슐화 원칙을 일부 위반하므로, 프로덕션 코드에서 이 프로퍼티에 직접 접근하지 않도록 주의해야 합니다.

// then
result shouldBe comment
verify { commentRepository.findByIdOrNull(id) }
verify { commentService.findById(id) }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

불필요한 verification 호출을 제거하세요.

commentService.findById(id)를 verify하는 것은 테스트 대상인 getById 메서드에서 내부적으로 호출하는 메서드를 검증하는 것입니다. 이는 구현 세부사항을 테스트하는 것으로 부적절합니다.

다음과 같이 수정하세요:

  result shouldBe comment
  verify { commentRepository.findByIdOrNull(id) }
- verify { commentService.findById(id) }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
verify { commentService.findById(id) }
result shouldBe comment
verify { commentRepository.findByIdOrNull(id) }
🤖 Prompt for AI Agents
In
src/test/kotlin/gomushin/backend/schedule/domain/service/CommentServiceTest.kt
at line 121, remove the verification call for commentService.findById(id)
because verifying internal method calls of the method under test exposes
implementation details. Simply delete the verify { commentService.findById(id) }
line to fix this.

Copy link
Contributor

@kimyeoungrok kimyeoungrok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿 수고했어 시험기간이라 미리 못봐서 미안 ㅎㅎ

fun setup() {
SpringContextHolder.context = mockApplicationContext
every { mockApplicationContext.getBean(AppEnv::class.java) } returns mockAppEnv
every { mockAppEnv.getId() } returns "test-env"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 원래 코드는 yml의 spring.application.name에 있는 값을 가져오는 걸로 알고있는데 지금 test yml보니깐 거기는 "backend"로 되어있던데 "test-env"로 한 이유가 궁금해

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 test yml 에 있는거 까먹고 그냥 하드코딩했어
사실 이건 중요한거 아니고, lazyInit 예외를 막으려고 넣은거라..

commentService.upsert(null, letterId, authorId, nickname, upsertCommentRequest)

// then
verify { commentService.save(any()) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

알아보니깐 verify는 스터빙한 객체의 메서드가 제대로 작동하는지 보는거라네(commentService는 실제 객체) 밑에 coderabbit이 지적한 것처럼 commentService가 아니라 commentRepository가 되어야할듯

@HoyeongJeon HoyeongJeon merged commit 7fa6b55 into main Jul 13, 2025
1 check passed
@HoyeongJeon HoyeongJeon deleted the issue/#147-comment-test branch July 13, 2025 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants