Skip to content

Commit 7a71549

Browse files
committed
[#234] Partnership 라우터의 서비스 계층의 코드를 테스트하는 코드 작성
1 parent 60026ab commit 7a71549

File tree

4 files changed

+108
-16
lines changed

4 files changed

+108
-16
lines changed

.cursor/rules/eatsstu-rules.mdc

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
description: EATSSU-iOS 프로젝트에서 Cursor가 유의해야 할 점
3+
globs: *.swift
4+
alwaysApply: false
5+
---
6+
7+
# 문서 작성 요령
8+
9+
- 코드를 설계하거나 리팩터링을 할 때, 유의해야 할 점으로 메소드에 대한 설명을 적는 것.
10+
- 파라미터값과 리턴값으로 어떤 자료형을 사용하는 명시하는 것이 중요.
11+
- 클래스 안에서 사용하는 코드면 private 접근제한자를 명시할 것.
12+
- 그외에는 internal을 사용. internal은 Swift에서 기본 접근제한자이기 때문에 명시하지 말 것.
13+
- Framework에 해당하는 코드일 때는 public을 명시에서 앱 모듈에서 사용할 수 있게 명시할 것.

EATSSU/App/Sources/Data/Network/ServiceLayer/PartnershipService.swift

+16
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,20 @@ final class PartnershipService {
3434
}
3535
}
3636
}
37+
38+
/// 특정 제휴 상세 정보 조회 API 호출
39+
/// - Parameter partnershipId: 조회할 제휴 ID
40+
/// - Returns: 성공 시 `PartnershipDetailResponse`를 반환하는 Single, 실패 시 에러 전파
41+
func fetchPartnershipDetail(partnershipId: Int) -> Single<BaseResponse<PartnershipDetailResponse>> {
42+
provider.rx.request(.fetchPartnershipDetail(partnershipId: partnershipId))
43+
.flatMap { response -> Single<BaseResponse<PartnershipDetailResponse>> in
44+
do {
45+
let decoder = JSONDecoder()
46+
let baseResponse = try decoder.decode(BaseResponse<PartnershipDetailResponse>.self, from: response.data)
47+
return Single.just(baseResponse)
48+
} catch {
49+
return Single.error(error)
50+
}
51+
}
52+
}
3753
}

EATSSU/App/Tests/UnitTests/PartnershipRouterTests.swift

+75-16
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,30 @@
99

1010
import EATSSUKit
1111

12-
import XCTest
13-
1412
import Moya
13+
import RxBlocking
14+
import RxSwift
15+
import RxTest
16+
import XCTest
1517

1618
final class PartnershipRouterTests: XCTestCase {
1719
var provider: MoyaProvider<PartnershipRouter>!
20+
var service: PartnershipService!
21+
var disposeBag: DisposeBag!
1822

1923
override func setUp() {
2024
super.setUp()
2125
// 실제 서버에 요청을 보내기 위해 stub 기능을 제거합니다.
2226
provider = MoyaProvider<PartnershipRouter>()
27+
service = PartnershipService(provider: provider)
28+
disposeBag = DisposeBag()
29+
}
30+
31+
override func tearDown() {
32+
provider = nil
33+
service = nil
34+
disposeBag = nil
35+
super.tearDown()
2336
}
2437

2538
private func handleResponse(_ response: Response, for endpoint: String) {
@@ -45,6 +58,8 @@ final class PartnershipRouterTests: XCTestCase {
4558
print("\n" + String(repeating: "-", count: 50) + "\n")
4659
}
4760

61+
// MARK: - Router Tests
62+
4863
/// 전체 제휴 목록 조회 API 테스트 (실제 서버 요청)
4964
func testFetchAllPartnershipsResponse() {
5065
let expectation = expectation(description: "fetchAllPartnerships")
@@ -100,22 +115,66 @@ final class PartnershipRouterTests: XCTestCase {
100115
waitForExpectations(timeout: 10.0, handler: nil)
101116
}
102117

103-
/// 제휴 찜 등록/취소 API 테스트 (실제 서버 요청)
104-
func testTogglePartnershipFavoriteResponse() {
118+
// MARK: - Service Tests
119+
120+
/// 전체 제휴 목록 조회 Service 테스트
121+
func testFetchAllPartnershipsService() {
122+
let expectation = expectation(description: "전체 제휴 목록 조회 Service")
123+
124+
service.fetchAllPartnerships()
125+
.subscribe(
126+
onSuccess: { response in
127+
// JSON 응답 출력
128+
print("\n🔍 [FetchAllPartnerships Service] Response Details:")
129+
if let jsonData = try? JSONEncoder().encode(response),
130+
let prettyJSON = JSONPrettyPrinter.prettyPrintedJSONString(from: jsonData)
131+
{
132+
print("\n📦 Response Data Structure:")
133+
print(prettyJSON)
134+
} else {
135+
print("⚠️ JSON 변환 실패")
136+
}
137+
print("\n" + String(repeating: "-", count: 50) + "\n")
138+
139+
expectation.fulfill()
140+
},
141+
onFailure: { error in
142+
XCTFail("Service 호출 실패: \(error.localizedDescription)")
143+
}
144+
)
145+
.disposed(by: disposeBag)
146+
147+
wait(for: [expectation], timeout: 10.0)
148+
}
149+
150+
/// 제휴 상세 정보 조회 Service 테스트
151+
func testFetchPartnershipDetailService() {
152+
let expectation = expectation(description: "제휴 상세 정보 조회 Service")
105153
let partnershipId = 2
106-
let expectation = expectation(description: "togglePartnershipFavorite")
107154

108-
provider.request(.togglePartnershipFavorite(partnershipId: partnershipId)) { result in
109-
switch result {
110-
case let .success(response):
111-
XCTAssertEqual(response.statusCode, 200)
112-
XCTAssertFalse(response.data.isEmpty, "응답 데이터가 비어있습니다.")
113-
expectation.fulfill()
114-
case let .failure(error):
115-
XCTFail("togglePartnershipFavorite 실패: \(error)")
116-
}
117-
}
155+
service.fetchPartnershipDetail(partnershipId: partnershipId)
156+
.subscribe(
157+
onSuccess: { response in
158+
// JSON 응답 출력
159+
print("\n🔍 [FetchPartnershipDetail Service] Response Details:")
160+
if let jsonData = try? JSONEncoder().encode(response),
161+
let prettyJSON = JSONPrettyPrinter.prettyPrintedJSONString(from: jsonData)
162+
{
163+
print("\n📦 Response Data Structure:")
164+
print(prettyJSON)
165+
} else {
166+
print("⚠️ JSON 변환 실패")
167+
}
168+
print("\n" + String(repeating: "-", count: 50) + "\n")
169+
170+
expectation.fulfill()
171+
},
172+
onFailure: { error in
173+
XCTFail("Service 호출 실패: \(error.localizedDescription)")
174+
}
175+
)
176+
.disposed(by: disposeBag)
118177

119-
waitForExpectations(timeout: 10.0, handler: nil)
178+
wait(for: [expectation], timeout: 10.0)
120179
}
121180
}

EATSSU/Project.swift

+4
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ let project = Project(
214214
sources: ["App/Tests/UnitTests/**"],
215215
dependencies: [
216216
.target(name: "EATSSU-DEV"),
217+
218+
.external(name: "RxTest"),
219+
.external(name: "RxBlocking"),
220+
217221
],
218222
settings: projectSettings
219223
),

0 commit comments

Comments
 (0)