Skip to content

API 직렬화 라이브러리를 Kotlin Serialization으로 통합#729

Open
boiledeggg wants to merge 19 commits into
developfrom
refactor/migrate-gson-to-serialization
Open

API 직렬화 라이브러리를 Kotlin Serialization으로 통합#729
boiledeggg wants to merge 19 commits into
developfrom
refactor/migrate-gson-to-serialization

Conversation

@boiledeggg
Copy link
Copy Markdown
Member

@boiledeggg boiledeggg commented Apr 30, 2026

요약

  • 직렬화 라이브러리를 Kotlinx Serialzation으로 통합 (Gson 제거)
  • 가능한 모든 응답 클래스들을 DefaultResponse로 래핑
  • 응답에 데이터를 포함하지 않는 API의 DefaultResponse 제너릭을 Nothing이 아닌 Unit으로 설정
  • @Named 어노테이션을 Qualifier로 대체

설명

익성님이 제보해주신 에러를 확인해보니, 응답이 DefaultResponse<Nothing>으로 되어있으면 Kotlin-Serialization이 직렬화를 하지 못해 발생하는 것이었습니다. 

  • Kotlin-Serialization의 경우:

    • Nothing을 사용하면 해당 필드에 어떠한 값도 할당될 수 없도록 제한한다고 합니다.
    • 따라서 @Serialzable을 찾을 수 없다는 런타임 에러가 발생한 것으로 파악됩니다.
  • Gson을 사용하는 경우:

    • Nothing을 제너릭으로 넘기면 인스턴스화가 불가능하다고 파악해 그냥 null을 할당한다고 합니다.
    • DefaultResponse<Nothing>Gson을 사용하는 케이스가 있었는데 여기선 에러가 발생하지 않았습니다.

앞으로 위와 같은 런타임 오류를 방지하기 위해 직렬화 라이브러리를 Kotlin Serialization으로 통합했습니다.
그리고 Nothing 사용이 불가해 응답이 없는 API에 대해선 DefaultResponse 타입으로 응답을 받도록 수정했습니다.

인지하시고 리뷰해주시면 감사하겠습니다.

테스트

  • 요청에 따라 테스트 통과 여부를 첨부합니다.
  • 응답이 복잡한 API에 대해서만 테스트 코드를 추가했다는 점 참고바랍니다.
image

Summary by CodeRabbit

릴리스 노트

  • Refactor

    • 내부 네트워크 요청 및 응답 구조 최적화
    • API 응답 모델 통일 및 일관성 개선
    • 널 안전성 강화로 안정성 개선
  • Chores

    • 직렬화 라이브러리 내부 업데이트
    • 의존성 주입 시스템 개선

- DefaultResponse를 적용
- DefaultResponse를 적용
- Gson에서 Kotlin Serialization으로 마이그레이션
- DefaultResponse를 적용
- Gson에서 Kotlin Serialization으로 마이그레이션
- DefaultResponse 타입을 Nothing에서 Unit으로 변경
- Gson에서 Kotlin Serialization으로 마이그레이션
- DefaultResponse 타입을 Nothing에서 Unit으로 변경
- DefaultResponse 타입을 Nothing에서 Unit으로 변경
- DefaultResponse를 적용
- Gson에서 Kotlin Serialization으로 마이그레이션
- DefaultResponse 타입을 Nothing에서 Unit으로 변경
- Gson에서 Kotlin Serialization으로 마이그레이션
- Gson에서 Kotlin Serialization으로 마이그레이션
- Gson에서 Kotlin Serialization으로 마이그레이션
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Walkthrough

Kotlinx.serialization로 Retrofit 변환기 통합, 여러 Retrofit 응답을 DefaultResponse<T> 기반으로 통합하고 Gson 의존성 제거, Hilt DI 한정자를 @Named에서 커스텀(@Default,@Library,@KuringSpace)으로 전환했습니다. 관련 DTO·서비스 시그니처·매퍼·저장소·페이저·테스트·테스트 픽스처가 일괄 수정되었습니다.

Changes

Kotlinx Serialization 및 DefaultResponse 통합

Layer / File(s) Summary
데이터 형태 변경
data/remote/.../response/*Response.kt, data/remote/.../DefaultResponse.kt
다수의 *ListResponse 타입 삭제/대체; 응답 모델들이 @Serializable/@SerialName으로 전환되고 일부 필드(예: commentCount, isImportant 기본값, SignInResponse 구조)가 변경됨. DefaultResponse의 Gson 어노테이션 제거.
네트워크/컨버터 제공
data/remote/.../NetworkModule.kt, data/remote/.../NetworkQualifier.kt, build-logic/.../RetrofitPlugin.kt, gradle/libs.versions.toml
kotlinx.serialization 기반 Converter.Factory 제공자 추가. Retrofit Gson 컨버터 제거(플러그인·libs 버전 카탈로그 반영). 커스텀 DI 한정자(@Default,@Library,@KuringSpace) 추가.
Retrofit 서비스/클라이언트 시그니처
data/remote/.../Service.kt, .../Client.kt
여러 Retrofit 인터페이스 및 클라이언트가 반환 타입을 DefaultResponse<...> 또는 DefaultResponse<Unit> 등으로 변경. SignIn 등 일부는 래핑 형태로 변경.
DI 모듈/바인딩
data/remote/.../di/*Module.kt
기존 @Named(...) 주입을 새 커스텀 한정자(@Default, @Library, @KuringSpace)로 교체; Retrofit 제공자 시그니처에 Converter.Factory 주입 반영.
도메인 매퍼·저장소·페이저
data/notice/.../ResponseToDomain.kt, data/staff/.../ResponseToDomain.kt, data/notice/.../repository/*, source/*Mediator.kt, data/academicevent/.../AcademicEventRepositoryImpl.kt
매퍼/리포지토리가 DefaultResponse<T> 구조에 맞게 리시버/널 처리 변경. DB 삽입·페이징 로직에서 response.data 널 검사(또는 isSuccessAndDataExists)를 추가하여 널 안전성 강화.
테스트 및 테스트 픽스처
data/remote/src/test/..., data/remote/src/test/resources/api-response/*, data/notice/test/*, data/department/test/*, data/library/test/*
테스트가 DefaultResponse 구조로 변경되어 모킹·어설션이 unwrapped response.data 중심으로 수정됨. 여러 새 단위 테스트(Club/Department/Staff/KuringSpace/User) 및 JSON 픽스처 추가/업데이트.
기타 마이그레이션 세부
data/user/..., data/remote/.../verification/*, noticecomment/*, report/*
DefaultResponse<Nothing>DefaultResponse<Unit> 변경, 요청 DTO에 @Serializable 추가 등 부수적 변경.

Sequence Diagram

sequenceDiagram
    participant Client as UI/UseCase
    participant Repo as Repository
    participant Remote as Retrofit(Service)
    participant DB as Database
    Client->>Repo: fetchItems()
    Repo->>Remote: service.fetchSomething() (DefaultResponse<T>)
    Remote-->>Repo: DefaultResponse[data=list] / resultCode
    alt isSuccessAndDataExists
        Repo->>DB: map & insert(entities)
        DB-->>Repo: insert result
        Repo-->>Client: mapped domain list
    else failure or data null
        Repo-->>Client: throw IllegalStateException(resultMsg) or return empty list
    end
Loading

Possibly related PRs

  • ku-ring/KU-Ring-Android#667: DefaultResponse 제네릭·서비스 반환 타입 변경과 직접적으로 연관된 PR입니다.
  • ku-ring/KU-Ring-Android#599: 공지 RemoteMediator 및 페이징 처리 변경과 중복 또는 연속된 수정 영역을 가집니다.
  • ku-ring/KU-Ring-Android#573: 학사 일정 클라이언트/서비스/저장소 관련 변경을 이어가는 PR로서 밀접 관련됩니다.

🐰 Gson 안녕, 직선으로 뛸래,
SerialName 달고 데이터 정렬해,
DefaultResponse로 한 줄에 묶고,
Named는 벗겨, 커스텀 한정자 입혀,
테스트와 DB도 같이 춤추네. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.02% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 풀 리퀘스트의 주요 목표를 명확히 요약하고 있습니다. 'Kotlin Serialization으로 통합'이라는 핵심 변경사항을 정확히 나타냅니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/migrate-gson-to-serialization

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@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: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/KuringBotQueryCountResponse.kt (1)

13-16: ⚠️ Potential issue | 🔴 Critical

@SerialName 어노테이션 누락으로 인한 역직렬화 실패

leftAskCount, maxAskCount 필드에 @SerialName 어노테이션이 없습니다. 프로젝트의 모든 다른 응답 DTO(UserDataResponse, SearchStaffResponse, DefaultResponse 등)는 모든 필드에 @SerialName을 적용하고 있으며, 코딩 가이드라인에서도 "모든 필드에 @SerialName 어노테이션을 사용하여 실제 API 필드명과 명시적으로 매핑"하도록 요구하고 있습니다. 이 어노테이션이 없으면 Kotlinx Serialization이 필드를 올바르게 역직렬화하지 못할 수 있습니다.

실제 API 응답의 필드명 형식(snake_case 또는 camelCase)을 확인하여 적절한 @SerialName 값을 추가해주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/KuringBotQueryCountResponse.kt`
around lines 13 - 16, KuringBotQueryCountData is missing `@SerialName` annotations
on its properties (leftAskCount, maxAskCount) which breaks kotlinx.serialization
deserialization; update the data class KuringBotQueryCountData to add
`@SerialName`("...") for each property using the exact API field names (e.g.
"left_ask_count" or "leftAskCount" and "max_ask_count" or "maxAskCount"
depending on the API), apply `@SerialName` to both leftAskCount and maxAskCount,
and ensure imports for kotlinx.serialization.SerialName are present so the
serializer maps JSON fields explicitly.
🧹 Nitpick comments (1)
data/remote/src/test/java/com/ku_stacks/ku_ring/remote/ApiAbstract.kt (1)

14-14: ⚡ Quick win

테스트 Json 설정을 프로덕션 설정과 재사용하도록 맞추는 게 좋습니다.

Line 14의 로컬 Json 설정이 Line 45에서 직접 사용되어, 추후 프로덕션 Json 옵션이 바뀔 때 테스트가 다른 규칙으로 파싱할 수 있습니다. 공통 팩토리/상수 재사용으로 설정 드리프트를 막는 것을 권장합니다.

Also applies to: 45-45

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/ApiAbstract.kt` at
line 14, The test's local Json instance (private val json) diverges from
production and risks config drift; replace it by reusing the shared production
Json factory/constant (e.g., JsonFactory.provideJson() or a common
JsonConfig/COMMON_JSON instance) instead of declaring a local Json, and update
all usages (including where json is directly used at call sites) to reference
that shared provider; ensure the shared provider uses Json { ignoreUnknownKeys =
true } (or the current production options) so tests and production parse with
identical settings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@data/academicevent/src/main/java/com/ku_stacks/ku_ring/academicevent/repository/AcademicEventRepositoryImpl.kt`:
- Around line 29-30: 현재 코드 in AcademicEventRepositoryImpl uses
response.data?.toEntity() without checking response.isSuccess, which can persist
invalid data when isSuccess == false; update the logic to verify
response.isSuccess is true and response.data is non-null before calling
toEntity(), otherwise throw IllegalStateException(response.resultMsg) (i.e., use
a conditional like if (response.isSuccess == true && response.data != null) {
val eventEntities = response.data.toEntity() } else { throw
IllegalStateException(response.resultMsg) }) so both success flag and payload
are validated.

In
`@data/notice/src/main/java/com/ku_stacks/ku_ring/notice/repository/NoticeRepositoryImpl.kt`:
- Around line 142-143: In NoticeRepositoryImpl, don't mask remote failures by
converting a null response.data into emptyList; instead explicitly handle the
null case from noticeClient.fetchSubscribe: if fetchSubscribe returns null data,
throw or propagate a descriptive exception (e.g., RemoteFetchException or
IllegalStateException) so callers can distinguish actual empty subscriptions
from a failed fetch; keep the successful path mapping data.map { it.koreanName }
and only return emptyList when the response is a valid empty list, not when data
is null.

In
`@data/notice/src/main/java/com/ku_stacks/ku_ring/notice/source/DepartmentNoticeMediator.kt`:
- Around line 46-47: The exception message incorrectly refers to
"noticeResponse" when the null check is on noticeResponse.data; update the
thrown IllegalStateException messages in DepartmentNoticeMediator where you have
checks like noticeResponse.data ?: throw IllegalStateException("noticeResponse
is null") to accurately reference noticeResponse.data (e.g.,
"noticeResponse.data is null" or include both noticeResponse and data), so
errors point to the real failing variable; adjust the same change for the other
occurrence around the second null-check as well.

In
`@data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/response/DepartmentResponse.kt`:
- Around line 8-10: The DepartmentResponse DTO is missing `@SerialName` on the
properties name and korName; update the data class in DepartmentResponse.kt to
annotate both 'name' and 'korName' with the exact API field names (matching the
API’s keys) just like 'shortName' is annotated with `@SerialName`("hostPrefix"),
and ensure kotlinx.serialization.SerialName is imported; verify and use the
API’s canonical key strings (e.g., "name" or snake_case "kor_name") when adding
the annotations.

In
`@data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/DepartmentNoticeResponse.kt`:
- Around line 6-15: DepartmentNoticeResponse is missing `@SerialName` annotations
on its properties; add `@SerialName`("...") to each property (id, articleId,
postedDate, subject, url, category, important, commentCount) to exactly match
the API field names and ensure stable deserialization, and import
kotlinx.serialization.SerialName; keep the `@Serializable` annotation on the data
class and ensure the string values in `@SerialName` match the API contract (e.g.,
use the exact JSON keys for articleId, postedDate, etc.).

In
`@data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/request/RegisterUserRequest.kt`:
- Around line 5-6: The RegisterUserRequest data class is missing a `@SerialName`
on the token property; update the RegisterUserRequest definition to annotate the
token property with `@SerialName` using the exact API field name (e.g.,
`@SerialName`("token")) and add the necessary import
(kotlinx.serialization.SerialName) so serialization contracts are explicit for
the RegisterUserRequest.token field.

In
`@data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/KuringBotQueryCountResponse.kt`:
- Around line 6-10: The DTO KuringBotQueryCountResponse and its nested
KuringBotQueryCountData are missing `@SerialName` annotations on their properties
(code, message, data, leftAskCount, maxAskCount); update the data class
definitions for KuringBotQueryCountResponse and KuringBotQueryCountData to add
`@SerialName`("code"), `@SerialName`("message"), `@SerialName`("data") on the
top-level properties and `@SerialName`("leftAskCount"), `@SerialName`("maxAskCount")
on the nested properties so they match the project's serialization convention
and other DTOs like UserDataResponse.

In
`@data/user/src/main/java/com/ku_stacks/ku_ring/user/repository/UserRepositoryImpl.kt`:
- Around line 94-97: The current mapping in UserRepositoryImpl (inside the map {
response -> with(response) { ... } } block) treats responses with isSuccess ==
true but data == null as successful; change the condition to require data
non-null (e.g., if (isSuccess && data != null) { pref.accessToken =
data.accessToken } else { treat as failure: log an error with resultMsg and the
missing-data context and return/fail appropriately }). Ensure you reference the
response fields isSuccess, data, resultMsg and the side-effect pref.accessToken
so the repository consistently fails when the success flag is true but payload
is missing.

---

Outside diff comments:
In
`@data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/KuringBotQueryCountResponse.kt`:
- Around line 13-16: KuringBotQueryCountData is missing `@SerialName` annotations
on its properties (leftAskCount, maxAskCount) which breaks kotlinx.serialization
deserialization; update the data class KuringBotQueryCountData to add
`@SerialName`("...") for each property using the exact API field names (e.g.
"left_ask_count" or "leftAskCount" and "max_ask_count" or "maxAskCount"
depending on the API), apply `@SerialName` to both leftAskCount and maxAskCount,
and ensure imports for kotlinx.serialization.SerialName are present so the
serializer maps JSON fields explicitly.

---

Nitpick comments:
In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/ApiAbstract.kt`:
- Line 14: The test's local Json instance (private val json) diverges from
production and risks config drift; replace it by reusing the shared production
Json factory/constant (e.g., JsonFactory.provideJson() or a common
JsonConfig/COMMON_JSON instance) instead of declaring a local Json, and update
all usages (including where json is directly used at call sites) to reference
that shared provider; ensure the shared provider uses Json { ignoreUnknownKeys =
true } (or the current production options) so tests and production parse with
identical settings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 05de3451-c2f0-4a2e-8e1c-834d6edb6d1e

📥 Commits

Reviewing files that changed from the base of the PR and between 7cad12a and 410048f.

📒 Files selected for processing (76)
  • build-logic/src/main/kotlin/com/ku_stacks/ku_ring/buildlogic/primitive/RetrofitPlugin.kt
  • data/academicevent/src/main/java/com/ku_stacks/ku_ring/academicevent/repository/AcademicEventRepositoryImpl.kt
  • data/academicevent/src/test/java/com/ku_stacks/ku_ring/academicevent/AcademicEventTestUtil.kt
  • data/academicevent/src/test/java/com/ku_stacks/ku_ring/academicevent/AcademicRepositoryTest.kt
  • data/department/src/test/java/com/ku_stacks/ku_ring/department/repository/DepartmentRepositoryTest.kt
  • data/notice/src/main/java/com/ku_stacks/ku_ring/notice/mapper/ResponseToDomain.kt
  • data/notice/src/main/java/com/ku_stacks/ku_ring/notice/repository/NoticeRepositoryImpl.kt
  • data/notice/src/main/java/com/ku_stacks/ku_ring/notice/source/CategoryNoticeMediator.kt
  • data/notice/src/main/java/com/ku_stacks/ku_ring/notice/source/DepartmentNoticeMediator.kt
  • data/notice/test/src/main/java/com/ku_stacks/ku_ring/notice/test/NoticeTestUtil.kt
  • data/remote/AGENTS.md
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/academicevent/AcademicEventClient.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/academicevent/AcademicEventService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/academicevent/di/AcademicEventModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/academicevent/response/AcademicEventListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/club/di/ClubModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/DepartmentService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/di/DepartmentModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/request/DepartmentSubscribeRequest.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/response/DepartmentListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/response/DepartmentResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/library/di/LibraryModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/library/response/LibraryRoomBranchResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/library/response/LibraryRoomListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/library/response/LibraryRoomResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/library/response/LibraryRoomSeatResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/library/response/LibraryRoomTypeResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/library/response/LibrarySeatResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/NoticeClient.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/NoticeService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/di/NoticeModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/request/SubscribeRequest.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/CategoryResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/DepartmentNoticeListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/DepartmentNoticeResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/NoticeListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/NoticeResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SearchNoticeDataResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SearchNoticeListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SearchNoticeResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SubscribeListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/noticecomment/NoticeCommentClient.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/noticecomment/NoticeCommentService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/noticecomment/di/NoticeCommentModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/report/ReportClient.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/report/ReportService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/report/di/ReportModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/space/di/KuringSpaceModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/space/response/AppVersionResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/staff/StaffClient.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/staff/StaffService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/staff/di/StaffModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/staff/response/SearchStaffDataResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/staff/response/SearchStaffListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/staff/response/SearchStaffResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/UserClient.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/UserService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/di/UserModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/request/AcademicEventNotificationRequest.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/request/FeedbackRequest.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/request/RegisterUserRequest.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/KuringBotQueryCountResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/SignInResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/util/DefaultResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/util/NetworkModule.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/util/NetworkQualifier.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/verification/VerificationClient.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/verification/VerificationService.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/verification/di/VerficationModule.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/AcademicEventServiceTest.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/ApiAbstract.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/NoticeServiceTest.kt
  • data/remote/src/test/resources/api-response/GetNoticeCommentResponse.json
  • data/staff/src/main/java/com/ku_stacks/ku_ring/staff/mapper/ResponseToDomain.kt
  • data/user/src/main/java/com/ku_stacks/ku_ring/user/repository/UserRepositoryImpl.kt
  • gradle/libs.versions.toml
💤 Files with no reviewable changes (10)
  • build-logic/src/main/kotlin/com/ku_stacks/ku_ring/buildlogic/primitive/RetrofitPlugin.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/staff/response/SearchStaffListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/response/DepartmentListResponse.kt
  • gradle/libs.versions.toml
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/NoticeListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/academicevent/response/AcademicEventListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SubscribeListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SearchNoticeListResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/util/DefaultResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/DepartmentNoticeListResponse.kt

Comment on lines 7 to +9
data class SignInResponse(
@SerialName("code") val code: Int,
@SerialName("message") val message: String,
@SerialName("data") val data: SignInToken,
) {
@Serializable
data class SignInToken(
@SerialName("accessToken") val accessToken: String,
)

val isSuccess: Boolean get() = (code == 200)
}
@SerialName("accessToken") val accessToken: String,
)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

이건 테스트 된건가요?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

직접 확인은 했었는데, 확실한 검증을 위해 테스트 코드 추가해뒀습니다!

a9e3478

Comment thread data/remote/src/test/java/com/ku_stacks/ku_ring/remote/NoticeServiceTest.kt Outdated
Copy link
Copy Markdown
Collaborator

@l2hyunwoo l2hyunwoo left a comment

Choose a reason for hiding this comment

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

의존성에서 gson 날라간 것 확인

추가로 API 단 unit test 전체 통과한거 스샷찍어서 올려주심 감사용

Copy link
Copy Markdown
Contributor

@ikseong00 ikseong00 left a comment

Choose a reason for hiding this comment

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

많이 수정됐군요.. 고생하셨습니다!

- 동아리 목록 및 동아리 정보
- 학과 목록
- 깃허브에 저장된 앱 최소 스펙
- 교수 목록
- 로그인 응답
@boiledeggg
Copy link
Copy Markdown
Member Author

@l2hyunwoo PR 코멘트에 스샷 추가해뒀습니다! (저거 말하신거 맞죠?)

@boiledeggg boiledeggg requested review from ikseong00 and l2hyunwoo May 5, 2026 07:49
Copy link
Copy Markdown
Contributor

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
data/notice/src/test/java/com/ku_stacks/ku_ring/notice/NoticeRepositoryTest.kt (1)

78-83: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

성공 케이스 테스트의 기대값은 non-null로 고정해 계약을 명확히 검증해 주세요.

Line 78의 nullable 기대값은 성공 경로 검증을 약하게 만듭니다. data를 명시적으로 non-null로 두고 assertEquals로 비교하는 편이 명확합니다.

제안 수정안
-        val expected = mockSubscribeList.data?.map { it.koreanName }
+        val expected = requireNotNull(mockSubscribeList.data).map { it.koreanName }
@@
-        assert(result == expected)
+        assertEquals(expected, result)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@data/notice/src/test/java/com/ku_stacks/ku_ring/notice/NoticeRepositoryTest.kt`
around lines 78 - 83, The test uses a nullable expected value
(mockSubscribeList.data?.map { it.koreanName }) which weakens the success
assertion; change it to a non-null expectation and use an equality assertion
method. Replace the nullable mapping with a non-null mapping (e.g.,
mockSubscribeList.data!!.map { it.koreanName } or construct a non-null expected
list) and assert using assertEquals(expected,
repository.fetchSubscriptionFromRemote(mockToken)) instead of assert(result ==
expected) so fetchSubscriptionFromRemote is validated against a guaranteed
non-null expected value.
🧹 Nitpick comments (6)
data/remote/src/test/java/com/ku_stacks/ku_ring/remote/KuringSpaceServiceTest.kt (1)

32-35: ⚡ Quick win

takeRequest() 결과도 검증해서 회귀 감지를 강화해 주세요.

요청을 꺼내기만 하고 검증하지 않으면 잘못된 경로/메서드 호출이 숨어도 테스트가 통과할 수 있습니다. 최소한 path, method는 assert 하는 것이 좋습니다.

예시 diff
         // when
         val response = service.getMinimumAppVersion()
-        mockWebServer.takeRequest()
+        val request = mockWebServer.takeRequest()
 
         // then
+        assertEquals("GET", request.method)
+        assertEquals("/minimum-app-version", request.path) // 실제 엔드포인트에 맞게 조정
         assertEquals("2.0.0", response.minimumAppVersion)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/KuringSpaceServiceTest.kt`
around lines 32 - 35, 테스트에서 mockWebServer.takeRequest()로 꺼낸 요청(Request)을 검증하지 않아
경로/메서드 변경이 누락될 수 있으니 KuringSpaceServiceTest 내 mockWebServer.takeRequest() 호출 결과를
변수(request)로 받아 request.path와 request.method를 assert하여 예상 엔드포인트와 HTTP 메서드와 일치하는지
확인하고 기존의 assertEquals("2.0.0", response.minimumAppVersion)도 유지하세요; 예를 들어
request.path가 기대값(예: "/expected/path")과 request.method가 기대값(예: "GET")인지 검증하도록
수정하세요.
data/remote/src/test/java/com/ku_stacks/ku_ring/remote/UserServiceTest.kt (1)

60-79: ⚡ Quick win

JUnit4 스타일이 JUnit5 컨벤션과 맞지 않습니다.

이 파일은 **/*Test.kt 패턴에 해당하며, 코딩 가이드라인에 따라 JUnit5를 사용해야 합니다. 현재 코드는 org.junit.Testorg.junit.Assert.assertEquals(JUnit4)를 사용하고 있으므로, org.junit.jupiter.api 패키지의 JUnit5 애노테이션과 어설션으로 마이그레이션하는 것이 좋습니다.

마이그레이션 예시
-import org.junit.Assert.assertEquals
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/UserServiceTest.kt`
around lines 60 - 79, The test uses JUnit4 imports/annotations; switch to JUnit5
by replacing org.junit.Test with org.junit.jupiter.api.Test and replace
org.junit.Assert.assertEquals calls with
org.junit.jupiter.api.Assertions.assertEquals (update any other JUnit4 imports
similarly), keeping the test body (the `fun `sign in test`` method,
`AuthorizeUserRequest`, `service.signIn(...)`, `mockWebServer.takeRequest()` and
coroutine `runTest` usage) unchanged so only the import/annotation and assertion
references are migrated to JUnit5 conventions.
data/remote/src/test/java/com/ku_stacks/ku_ring/remote/StaffServiceTest.kt (1)

31-33: ⚡ Quick win

요청 검증이 빠져 있어 회귀 탐지력이 약합니다.

Line 32에서 takeRequest()만 호출하고 경로/쿼리를 검증하지 않아 content 파라미터 직렬화/전달 오류를 놓칠 수 있습니다. 최소한 path와 query(content=김은이)를 assert 해주세요.

예시 보강 diff
         val response = service.fetchStaffs(content = "김은이")
-        mockWebServer.takeRequest()
+        val request = mockWebServer.takeRequest()
+        assertEquals("GET", request.method)
+        assertEquals("/staff?content=%EA%B9%80%EC%9D%80%EC%9D%B4", request.path)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/StaffServiceTest.kt`
around lines 31 - 33, 테스트에서 요청 검증이 빠져 있어 직렬화/전달 오류를 놓칠 수 있으니
mockWebServer.takeRequest() 호출의 반환값을 받아 request 객체로 저장하고 경로 및 쿼리 검증을 추가하세요:
service.fetchStaffs(...) 호출 뒤 mockWebServer.takeRequest() 대신 val request =
mockWebServer.takeRequest()를 사용하고 request.path 또는
request.requestUrl.queryParameter("content")를 이용해 expected path와 content=김은이 쿼리가
포함되는지(assertEquals/assertTrue) 확인하도록 수정하세요; 관련 식별자는 fetchStaffs 및
mockWebServer.takeRequest()입니다.
data/remote/src/test/java/com/ku_stacks/ku_ring/remote/DepartmentServiceTest.kt (1)

34-34: ⚡ Quick win

테스트 내 throw IllegalStateException 대신 단언 API 사용 권장

?: throw IllegalStateException(...) 패턴은 테스트 프레임워크의 단언 실패 메시지 대신 일반 예외 스택 트레이스만 출력합니다. assertNotNull이나 Kotlin 표준 라이브러리의 requireNotNull을 사용하면 더 명확한 실패 메시지를 얻을 수 있습니다.

♻️ 제안 수정
-        val departments = response.data ?: throw IllegalStateException("Data should not be null")
+        assertNotNull("data should not be null", response.data)
+        val departments = requireNotNull(response.data)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/DepartmentServiceTest.kt`
at line 34, The test currently uses the Elvis throw pattern on response.data
(val departments = response.data ?: throw IllegalStateException(...)), which
yields poor failure output; replace it with a test assertion or Kotlin
null-check helper—e.g., call assertNotNull(response.data, "response.data should
not be null") from your test framework and then assign departments from the
asserted value, or use requireNotNull(response.data) { "response.data should not
be null" } to provide a clear failure message; update the line referencing
response.data / departments in DepartmentServiceTest.kt accordingly.
data/notice/src/main/java/com/ku_stacks/ku_ring/notice/repository/NoticeRepositoryImpl.kt (2)

142-146: ⚡ Quick win

실패 케이스에서 nullable 메시지를 그대로 예외에 넣지 않는 편이 안전합니다.

Line 145의 IllegalStateException(response.resultMsg)resultMsg == null일 때 원인 파악이 어려워집니다. 기본 메시지를 보강하거나 도메인 예외로 변환해 실패 이유를 보존해 주세요.

제안 수정안
-            else -> throw IllegalStateException(response.resultMsg)
+            else -> throw IllegalStateException(
+                response.resultMsg ?: "Failed to fetch subscriptions from remote"
+            )

Based on learnings: "Implement error handling in repository mappers rather than service definitions by catching specific exceptions (HttpRequestTimeoutException, ResponseException) and transforming them to domain-level exceptions".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@data/notice/src/main/java/com/ku_stacks/ku_ring/notice/repository/NoticeRepositoryImpl.kt`
around lines 142 - 146, The repository currently throws
IllegalStateException(response.resultMsg) in NoticeRepositoryImpl when
fetchSubscribe fails; change this to produce a non-null, informative
domain-level exception: when response.isSuccessAndDataExists is false, throw a
NoticeFetchException (or at minimum IllegalStateException) with a composed
message that includes a safe default for response.resultMsg (e.g.
response.resultMsg ?: "no message"), plus any available identifiers like
response.resultCode or the token, so the cause is preserved; also ensure
repository-level mapping catches transport exceptions (e.g.
HttpRequestTimeoutException, ResponseException) around
noticeClient.fetchSubscribe and rethrows them as the same domain
NoticeFetchException to centralize error handling.

167-173: ⚡ Quick win

하드코딩된 Dispatchers.IO 대신 주입된 ioDispatcher로 통일해 주세요.

Line 167은 테스트에서 주입한 디스패처를 우회하므로, 같은 저장소 내 디스패처 정책을 일관되게 맞추는 것이 좋습니다.

제안 수정안
-        withContext(Dispatchers.IO) {
+        withContext(ioDispatcher) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@data/notice/src/main/java/com/ku_stacks/ku_ring/notice/repository/NoticeRepositoryImpl.kt`
around lines 167 - 173, In NoticeRepositoryImpl replace the hardcoded
withContext(Dispatchers.IO) usage with the injected ioDispatcher so tests and
runtime use the same dispatcher policy: locate the coroutine block that calls
noticeClient.fetchNoticeList(query) and change the withContext call to use the
class-level or constructor-provided ioDispatcher (the injected
CoroutineDispatcher variable named ioDispatcher) so fetching and subsequent
logic (including noticeClient.fetchNoticeList and noticeDao.getSavedNoticeList)
run on the injected dispatcher.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@data/academicevent/src/main/java/com/ku_stacks/ku_ring/academicevent/repository/AcademicEventRepositoryImpl.kt`:
- Around line 29-31: The current branch swallows API failures by doing nothing
when response.isSuccessAndDataExists is false; update the block around response
and insertAcademicEventsIntoDB so that when isSuccessAndDataExists is false you
throw an appropriate exception (or call Result.failure) with the response
error/message to propagate the failure to suspendRunCatching callers; locate the
conditional that checks response.isSuccessAndDataExists in
AcademicEventRepositoryImpl (and any use of
response.data!!.toEntity()/insertAcademicEventsIntoDB) and add an else branch
that constructs and throws a descriptive exception (including response
error/details) so callers can distinguish success from API error.

In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/ClubServiceTest.kt`:
- Around line 5-10: The test class is using JUnit4 annotations
(org.junit.Before, org.junit.After, org.junit.Test) and JUnit4 asserts; migrate
ClubServiceTest to JUnit5 by replacing `@Before` with `@BeforeEach`, `@After` with
`@AfterEach` and `@Test` with org.junit.jupiter.api.Test, update imports to
org.junit.jupiter.api.* and switch assertions to
org.junit.jupiter.api.Assertions (e.g., assertEquals/assertNotNull/assertNull
from Assertions), and remove any leftover org.junit.* imports so all test
lifecycle and assertion symbols come from JUnit5.

In
`@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/KuringSpaceServiceTest.kt`:
- Around line 5-9: Update the test to use JUnit5 imports and annotations:
replace org.junit.Before, org.junit.After, org.junit.Test imports with
org.junit.jupiter.api.BeforeEach, org.junit.jupiter.api.AfterEach,
org.junit.jupiter.api.Test and swap org.junit.Assert.assertEquals to
org.junit.jupiter.api.Assertions.assertEquals; then update the annotations on
the test methods in KuringSpaceServiceTest (replace `@Before` -> `@BeforeEach`,
`@After` -> `@AfterEach`, `@Test` stays but ensure it is the JUnit5 `@Test`) so methods
using those annotations compile against JUnit5.

In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/StaffServiceTest.kt`:
- Around line 5-9: StaffServiceTest.kt is using JUnit4 imports (`@Before`, `@After`,
org.junit.Assert) but the repo requires JUnit5; update the test to use JUnit5
APIs by replacing org.junit.Before -> org.junit.jupiter.api.BeforeEach,
org.junit.After -> org.junit.jupiter.api.AfterEach, org.junit.Test ->
org.junit.jupiter.api.Test and switch assertions from
org.junit.Assert.assertEquals to org.junit.jupiter.api.Assertions.assertEquals
(and any other Assert methods to Assertions equivalents); ensure annotation
names on methods (e.g., methods currently annotated with `@Before/`@After) are
renamed to `@BeforeEach/`@AfterEach and adjust static imports if present.

---

Outside diff comments:
In
`@data/notice/src/test/java/com/ku_stacks/ku_ring/notice/NoticeRepositoryTest.kt`:
- Around line 78-83: The test uses a nullable expected value
(mockSubscribeList.data?.map { it.koreanName }) which weakens the success
assertion; change it to a non-null expectation and use an equality assertion
method. Replace the nullable mapping with a non-null mapping (e.g.,
mockSubscribeList.data!!.map { it.koreanName } or construct a non-null expected
list) and assert using assertEquals(expected,
repository.fetchSubscriptionFromRemote(mockToken)) instead of assert(result ==
expected) so fetchSubscriptionFromRemote is validated against a guaranteed
non-null expected value.

---

Nitpick comments:
In
`@data/notice/src/main/java/com/ku_stacks/ku_ring/notice/repository/NoticeRepositoryImpl.kt`:
- Around line 142-146: The repository currently throws
IllegalStateException(response.resultMsg) in NoticeRepositoryImpl when
fetchSubscribe fails; change this to produce a non-null, informative
domain-level exception: when response.isSuccessAndDataExists is false, throw a
NoticeFetchException (or at minimum IllegalStateException) with a composed
message that includes a safe default for response.resultMsg (e.g.
response.resultMsg ?: "no message"), plus any available identifiers like
response.resultCode or the token, so the cause is preserved; also ensure
repository-level mapping catches transport exceptions (e.g.
HttpRequestTimeoutException, ResponseException) around
noticeClient.fetchSubscribe and rethrows them as the same domain
NoticeFetchException to centralize error handling.
- Around line 167-173: In NoticeRepositoryImpl replace the hardcoded
withContext(Dispatchers.IO) usage with the injected ioDispatcher so tests and
runtime use the same dispatcher policy: locate the coroutine block that calls
noticeClient.fetchNoticeList(query) and change the withContext call to use the
class-level or constructor-provided ioDispatcher (the injected
CoroutineDispatcher variable named ioDispatcher) so fetching and subsequent
logic (including noticeClient.fetchNoticeList and noticeDao.getSavedNoticeList)
run on the injected dispatcher.

In
`@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/DepartmentServiceTest.kt`:
- Line 34: The test currently uses the Elvis throw pattern on response.data (val
departments = response.data ?: throw IllegalStateException(...)), which yields
poor failure output; replace it with a test assertion or Kotlin null-check
helper—e.g., call assertNotNull(response.data, "response.data should not be
null") from your test framework and then assign departments from the asserted
value, or use requireNotNull(response.data) { "response.data should not be null"
} to provide a clear failure message; update the line referencing response.data
/ departments in DepartmentServiceTest.kt accordingly.

In
`@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/KuringSpaceServiceTest.kt`:
- Around line 32-35: 테스트에서 mockWebServer.takeRequest()로 꺼낸 요청(Request)을 검증하지 않아
경로/메서드 변경이 누락될 수 있으니 KuringSpaceServiceTest 내 mockWebServer.takeRequest() 호출 결과를
변수(request)로 받아 request.path와 request.method를 assert하여 예상 엔드포인트와 HTTP 메서드와 일치하는지
확인하고 기존의 assertEquals("2.0.0", response.minimumAppVersion)도 유지하세요; 예를 들어
request.path가 기대값(예: "/expected/path")과 request.method가 기대값(예: "GET")인지 검증하도록
수정하세요.

In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/StaffServiceTest.kt`:
- Around line 31-33: 테스트에서 요청 검증이 빠져 있어 직렬화/전달 오류를 놓칠 수 있으니
mockWebServer.takeRequest() 호출의 반환값을 받아 request 객체로 저장하고 경로 및 쿼리 검증을 추가하세요:
service.fetchStaffs(...) 호출 뒤 mockWebServer.takeRequest() 대신 val request =
mockWebServer.takeRequest()를 사용하고 request.path 또는
request.requestUrl.queryParameter("content")를 이용해 expected path와 content=김은이 쿼리가
포함되는지(assertEquals/assertTrue) 확인하도록 수정하세요; 관련 식별자는 fetchStaffs 및
mockWebServer.takeRequest()입니다.

In `@data/remote/src/test/java/com/ku_stacks/ku_ring/remote/UserServiceTest.kt`:
- Around line 60-79: The test uses JUnit4 imports/annotations; switch to JUnit5
by replacing org.junit.Test with org.junit.jupiter.api.Test and replace
org.junit.Assert.assertEquals calls with
org.junit.jupiter.api.Assertions.assertEquals (update any other JUnit4 imports
similarly), keeping the test body (the `fun `sign in test`` method,
`AuthorizeUserRequest`, `service.signIn(...)`, `mockWebServer.takeRequest()` and
coroutine `runTest` usage) unchanged so only the import/annotation and assertion
references are migrated to JUnit5 conventions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 798c09b8-1ad9-473b-9168-25b7a4751f22

📥 Commits

Reviewing files that changed from the base of the PR and between 410048f and f36c428.

📒 Files selected for processing (25)
  • data/academicevent/src/main/java/com/ku_stacks/ku_ring/academicevent/repository/AcademicEventRepositoryImpl.kt
  • data/library/src/test/java/com/ku_stacks/ku_ring/library/LibraryTestUtil.kt
  • data/notice/src/main/java/com/ku_stacks/ku_ring/notice/repository/NoticeRepositoryImpl.kt
  • data/notice/src/main/java/com/ku_stacks/ku_ring/notice/source/DepartmentNoticeMediator.kt
  • data/notice/src/test/java/com/ku_stacks/ku_ring/notice/NoticeRepositoryTest.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/department/response/DepartmentResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/DepartmentNoticeResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SearchNoticeResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/KuringBotQueryCountResponse.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/ClubServiceTest.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/DepartmentServiceTest.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/KuringSpaceServiceTest.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/NoticeServiceTest.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/StaffServiceTest.kt
  • data/remote/src/test/java/com/ku_stacks/ku_ring/remote/UserServiceTest.kt
  • data/remote/src/test/resources/api-response/AppVersionResponse.json
  • data/remote/src/test/resources/api-response/ClubDetailResponse.json
  • data/remote/src/test/resources/api-response/ClubListResponse.json
  • data/remote/src/test/resources/api-response/DepartmentListResponse.json
  • data/remote/src/test/resources/api-response/DepartmentNoticeResponse.json
  • data/remote/src/test/resources/api-response/NoticeResponse.json
  • data/remote/src/test/resources/api-response/SearchNoticeResponse.json
  • data/remote/src/test/resources/api-response/SignInResponse.json
  • data/remote/src/test/resources/api-response/StaffSearchResponse.json
  • data/user/src/main/java/com/ku_stacks/ku_ring/user/repository/UserRepositoryImpl.kt
💤 Files with no reviewable changes (1)
  • data/library/src/test/java/com/ku_stacks/ku_ring/library/LibraryTestUtil.kt
✅ Files skipped from review due to trivial changes (6)
  • data/remote/src/test/resources/api-response/StaffSearchResponse.json
  • data/remote/src/test/resources/api-response/AppVersionResponse.json
  • data/remote/src/test/resources/api-response/SignInResponse.json
  • data/remote/src/test/resources/api-response/ClubListResponse.json
  • data/remote/src/test/resources/api-response/DepartmentListResponse.json
  • data/remote/src/test/resources/api-response/SearchNoticeResponse.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • data/notice/src/main/java/com/ku_stacks/ku_ring/notice/source/DepartmentNoticeMediator.kt
  • data/user/src/main/java/com/ku_stacks/ku_ring/user/repository/UserRepositoryImpl.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/notice/response/SearchNoticeResponse.kt
  • data/remote/src/main/java/com/ku_stacks/ku_ring/remote/user/response/KuringBotQueryCountResponse.kt

Copy link
Copy Markdown
Collaborator

@l2hyunwoo l2hyunwoo left a comment

Choose a reason for hiding this comment

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

확인했음! 고생하셨습니당

Copy link
Copy Markdown
Member

@mwy3055 mwy3055 left a comment

Choose a reason for hiding this comment

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

Nothing이 생각보다 큰 의미를 갖네요. 언젠가는 해야 할 작업이었는데 해주셔서 감사합니다.

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.

4 participants