Skip to content

[IDLE] 모킹 객체를 관리하는 Testing 모듈 구현 및 적용 #89

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 16, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public enum ModuleDependency {
}

public static let Core: TargetDependency = .project(target: "Core", path: .relativeToRoot("Projects/Core"))

public static let Testing: TargetDependency = .project(target: "Testing", path: .relativeToRoot("Projects/Testing"))
}

// External dependencies
Expand Down
32 changes: 27 additions & 5 deletions project/Projects/App/Sources/DIAssembly/DataAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ public struct DataAssembly: Assembly {
container.register(LocalStorageService.self) { _ in
return DefaultLocalStorageService()
}
container.register((any ApplyService).self) { _ in
DefaultApplyService()
}
container.register((any AuthService).self) { _ in
DefaultAuthService()
}
container.register((any CrawlingPostService).self) { _ in
DefaultCrawlingPostService()
}
container.register((any ExternalRequestService).self) { _ in
DefaultExternalRequestService()
}
container.register((any NotificationsService).self) { _ in
DefaultNotificationsService()
}
container.register((any NotificationTokenTransferService).self) { _ in
DefaultNotificationTokenTransferService()
}
container.register((any RecruitmentPostService).self) { _ in
DefaultRecruitmentPostService()
}
container.register((any UserInformationService).self) { _ in
DefaultUserInformationService()
}


// MARK: 캐싱 레포지토리
container.register(CacheRepository.self) { _ in
Expand All @@ -38,11 +63,8 @@ public struct DataAssembly: Assembly {
.inObjectScope(.container)

// MARK: 로컬에 저장된 유저정보 레포지토리
container.register(UserInfoLocalRepository.self) { resolver in
let localStorageService = resolver.resolve(LocalStorageService.self)!
return DefaultUserInfoLocalRepository(
localStorageService: localStorageService
)
container.register(UserInfoLocalRepository.self) { _ in
DefaultUserInfoLocalRepository()
}

// MARK: 회원가입 입력 검증 레포지토리
Expand Down
48 changes: 13 additions & 35 deletions project/Projects/App/Sources/DIAssembly/DomainAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,36 @@ public struct DomainAssembly: Assembly {

// MARK: UseCase
container.register(NotificationTokenUseCase.self) { _ in
return DefaultNotificationTokenUseCase()
DefaultNotificationTokenUseCase()
}
.inObjectScope(.container)

container.register(AuthInputValidationUseCase.self) { resolver in
let repository = resolver.resolve(AuthInputValidationRepository.self)!

return DefaultAuthInputValidationUseCase(repository: repository)
container.register(AuthInputValidationUseCase.self) { _ in
DefaultAuthInputValidationUseCase()
}

container.register(AuthUseCase.self) { _ in
return DefaultAuthUseCase()
DefaultAuthUseCase()
}

container.register(CenterProfileUseCase.self) { resolver in
let userProfileRepository = resolver.resolve(UserProfileRepository.self)!
let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)!
return DefaultCenterProfileUseCase(
userProfileRepository: userProfileRepository,
userInfoLocalRepository: userInfoLocalRepository
)
container.register(CenterProfileUseCase.self) { _ in
DefaultCenterProfileUseCase()
}

container.register(RecruitmentPostUseCase.self) { resolver in
let repository = resolver.resolve(RecruitmentPostRepository.self)!

return DefaultRecruitmentPostUseCase(
repository: repository
)
container.register(RecruitmentPostUseCase.self) { _ in
DefaultRecruitmentPostUseCase()
}

container.register(WorkerProfileUseCase.self) { resolver in
let userProfileRepository = resolver.resolve(UserProfileRepository.self)!
let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)!
return DefaultWorkerProfileUseCase(
userProfileRepository: userProfileRepository,
userInfoLocalRepository: userInfoLocalRepository
)
container.register(WorkerProfileUseCase.self) { _ in
DefaultWorkerProfileUseCase()
}

container.register(SettingScreenUseCase.self) { _ in
return DefaultSettingUseCase()
DefaultSettingUseCase()
}

container.register(CenterCertificateUseCase.self) { resolver in
let authRepository = resolver.resolve(AuthRepository.self)!
let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)!

return DefaultCenterCertificateUseCase(
authRepository: authRepository,
userInfoLocalRepository: userInfoLocalRepository
)
container.register(CenterCertificateUseCase.self) { _ in
DefaultCenterCertificateUseCase()
}
}
}
7 changes: 3 additions & 4 deletions project/Projects/Data/DataSource/Service/ApplyService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import Foundation

public class ApplyService: BaseNetworkService<ApplyAPI> {

public override init() { }
}
public protocol ApplyService: NetworkService where TagetAPI == ApplyAPI { }

public class DefaultApplyService: BaseNetworkService<ApplyAPI>, ApplyService { }
59 changes: 15 additions & 44 deletions project/Projects/Data/DataSource/Service/BaseNetworkService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,24 @@ import Alamofire
import Moya
import RxMoya

public class BaseNetworkService<TagetAPI: BaseAPI> {
public protocol NetworkService {

associatedtype TagetAPI: BaseAPI

func request(api: TagetAPI, with: RequestType) -> Single<Response>

func requestDecodable<T: Decodable>(api: TagetAPI, with: RequestType) -> Single<T>
}

public enum RequestType {
case plain
case withToken
}

public class BaseNetworkService<TagetAPI: BaseAPI>: NetworkService {
@Injected var keyValueStore: KeyValueStore

init() { }
public init() { }

private lazy var providerWithToken: MoyaProvider<TagetAPI> = {

Expand Down Expand Up @@ -177,11 +190,6 @@ public class BaseNetworkService<TagetAPI: BaseAPI> {
// MARK: DataRequest
public extension BaseNetworkService {

enum RequestType {
case plain
case withToken
}

private func _request(api: TagetAPI, provider: MoyaProvider<TagetAPI>) -> Single<Response> {

provider.rx
Expand Down Expand Up @@ -249,43 +257,6 @@ public extension BaseNetworkService {
request(api: api, with: with)
.map(T.self)
}

// // MARK: Request with Progress
// struct ProgressResponse<T: Decodable> {
//
// let progress: Double
// let data: T?
// }
//
// func requestDecodableWithProgress<T: Decodable>(api: TagetAPI) -> Single<ProgressResponse<T>> {
//
// Single<ProgressResponse<T>>.create { single in
//
// self.provider.rx
// .requestWithProgress(api)
// .subscribe(onNext: { response in
//
// if let result = response.response {
//
// do {
//
// let decoded = try result.map(T.self)
//
// let item = ProgressResponse<T>(
// progress: response.progress,
// data: decoded
// )
//
// single(.success(item))
//
// } catch {
//
// single(.failure(error))
// }
// }
// })
// }
// }
}

// MARK: HTTPResponseException+Extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import Foundation

public class AuthService: BaseNetworkService<AuthAPI> {

public override init() { }
}
public protocol AuthService: NetworkService where TagetAPI == AuthAPI { }

public class DefaultAuthService: BaseNetworkService<AuthAPI>, AuthService { }
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

public class CrawlingPostService: BaseNetworkService<CrawlingPostAPI> {
public override init() { }
}

public protocol CrawlingPostService: NetworkService where TagetAPI == CrawlingPostAPI { }

public class DefaultCrawlingPostService: BaseNetworkService<CrawlingPostAPI>, CrawlingPostService { }
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

public class ExternalRequestService: BaseNetworkService<ExtenalUrlAPI> {
public override init() { }
}

public protocol ExternalRequestService: NetworkService where TagetAPI == ExtenalUrlAPI { }

public class DefaultExternalRequestService: BaseNetworkService<ExtenalUrlAPI>, ExternalRequestService { }
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

public class NotificationTokenTransferService: BaseNetworkService<NotificationTokenAPI> {
public override init() { }
}

public protocol NotificationTokenTransferService: NetworkService where TagetAPI == NotificationTokenAPI { }

public class DefaultNotificationTokenTransferService: BaseNetworkService<NotificationTokenAPI>, NotificationTokenTransferService { }
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import Foundation

public class NotificationsService: BaseNetworkService<NotificationsAPI> {

public override init() { }
}
public protocol NotificationsService: NetworkService where TagetAPI == NotificationsAPI { }

public class DefaultNotificationsService: BaseNetworkService<NotificationsAPI>, NotificationsService { }
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

public class RecruitmentPostService: BaseNetworkService<RcruitmentPostAPI> {
public override init() { }
}

public protocol RecruitmentPostService: NetworkService where TagetAPI == RcruitmentPostAPI { }

public class DefaultRecruitmentPostService: BaseNetworkService<RcruitmentPostAPI>, RecruitmentPostService { }
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import Foundation

public class UserInformationService: BaseNetworkService<UserInformationAPI> {

public override init() { }
}
public protocol UserInformationService: NetworkService where TagetAPI == UserInformationAPI { }

public class DefaultUserInformationService: BaseNetworkService<UserInformationAPI>, UserInformationService { }
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public class KeyChainList: KeyValueStore {
try keyChain.removeAll()

// UserDefaults의 경우 수동으로 정보를 삭제합니다.
UserDefaults.standard.removeObject(forKey: Key.Auth.kaccessToken)
UserDefaults.standard.removeObject(forKey: Key.Auth.krefreshToken)
UserDefaults.standard.removeObject(forKey: KeyValueStoreKey.kaccessToken)
UserDefaults.standard.removeObject(forKey: KeyValueStoreKey.krefreshToken)
}

public func get(key: String) -> String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@ public protocol KeyValueStore {
func removeAll() throws
}

enum Key {
enum Auth {
static let kaccessToken = "idle_accessToken"
static let krefreshToken = "idle_refreshToken"
}
public enum KeyValueStoreKey {
public static let kaccessToken = "idle_accessToken"
public static let krefreshToken = "idle_refreshToken"
}

public extension KeyValueStore {

func getAuthToken() -> (accessToken: String, refreshToken: String)? {

guard let accessToken = get(key: Key.Auth.kaccessToken), let refreshToken = get(key: Key.Auth.krefreshToken) else {
guard let accessToken = get(key: KeyValueStoreKey.kaccessToken), let refreshToken = get(key: KeyValueStoreKey.krefreshToken) else {
return nil
}

Expand All @@ -34,7 +32,7 @@ public extension KeyValueStore {

func saveAuthToken(accessToken: String, refreshToken: String) throws {

try save(key: Key.Auth.kaccessToken, value: accessToken)
try save(key: Key.Auth.krefreshToken, value: refreshToken)
try save(key: KeyValueStoreKey.kaccessToken, value: accessToken)
try save(key: KeyValueStoreKey.krefreshToken, value: refreshToken)
}
}
21 changes: 0 additions & 21 deletions project/Projects/Data/DataTests/APITesting/TestAssembly.swift

This file was deleted.

Loading
Loading