apple/XCTest

[XCTest] Stubber에 대해서 알아보자 💉

lgvv 2022. 2. 20. 19:07

Stubber

 

이번 프로젝트에서 Stubber를 사용했었는데, 응????

devxoul님이 만드셨구나

 

Carte, Then, Stubber까지 벌써 세개나 !! 

나도 이런 개발자가 되어야지

 

https://github.com/devxoul/Stubber

 

GitHub - devxoul/Stubber: A minimal method stub for Swift

A minimal method stub for Swift. Contribute to devxoul/Stubber development by creating an account on GitHub.

github.com

 

 ✅ Stubber

내가 Stubber를 사용한 목적은 작은 프로젝트에서 테스트 코드를 작성하는데 네트워크를 들고 있어야 하는 경우가 있었는데, Stubber를 이용하여 테스트 환경을 구축하기 위함.

 

테스트 코드를 작성하면서 네트워크 상에서는 너무 변수가 많은데 이를 하나하나 다 가정하고 테스트 코드를 작성하는건 어렵다.

따라서 Stubber를 이용해서 네트워크를 주입한다고 생각하면 된다.

 

 

그럼 코드 예시로 한번 보자.

 

🟠 LocalNetworkStub.swift (테스트를 위한 코드)

import Foundation
import Stubber // 네트워크 상에서 너무 변수가 많으니까 가상의 네트워크에서 주입하는거
import RxSwift

@testable import FindCVS

class LocalNetworkStub: LocalNetwork {
    // LocalNetwork 상속 받아서 사용함.
    override func getLocation(by mapPoint: MTMapPoint) -> Single<Result<LocationData, URLError>> {
        return Stubber.invoke(getLocation, args: mapPoint)
    }
}

이 코드는 아래에 작성된 Network작업이 없이도 사용할 수 있게 해준다.

 

 

🟠 LocalNetwork.swift 

import RxSwift

class LocalNetwork {
    private let session: URLSession
    let api = LocalAPI()
    
    init(session: URLSession = .shared) {
        self.session = session
    }
    
    func getLocation(by mapPoint: MTMapPoint) -> Single<Result<LocationData, URLError>> {
        guard let url = api.getLocation(by: mapPoint).url else {
            return .just(.failure(URLError(.badURL)))
        }
        
        let request = NSMutableURLRequest(url: url)
        request.httpMethod = "GET"
        request.setValue("KakaoAK {Your API Key} ", forHTTPHeaderField: "Authorization")
        
        return session.rx.data(request: request as URLRequest)
            .map { data in
                do {
                    let locationData = try JSONDecoder().decode(LocationData.self, from: data)
                    return .success(locationData)
                } catch {
                    return .failure(URLError(.cannotParseResponse))
                }
            }
            .catch { _ in .just(Result.failure(URLError(.cannotLoadFromNetwork))) }
            .asSingle()
    }
}

 

🟠 LocationInformationModelTest.swift

stub을 적용한 테스트코드

위처럼 네트워크가 실제 연결이 아니여도 init을 해줄 수 있게 된다.

 

 

 

 

(참고)

https://hucet.tistory.com/98

 

[스몰토크] Swift Stubbing 통합테스트

단위테스트는 알고리즘을 검증하는 테스트입니다. 통합테스트를 하기 위해 어떤 것들이 필요한 지 알아봅시다. 통합테스트 우리는 객체간 메시지 통신을 어떻게 확인할 수 있을까요...? 객체간

hucet.tistory.com