2018년 12월 14일 금요일

XCTest 에서 비동기 통신 class를 테스트를 하려면?

https://developer.apple.com/documentation/xctest/asynchronous_tests_and_expectations/testing_asynchronous_operations_with_expectations


위 링크를 보면 좋은 예제가 있다.


만일 네트워크 RESTFul API를 요청 하는 함수들 과
응답에 결과를 delegate로 호출 해주는 방법으로 만든 클래스가 있다면

이 class의 unit 테스트를 만들려면 testcase 함수 에서는 응답이 오기전에 XCAssertEqual()등의 메서드를 호출 할 수 없다. 네트워크 응답을 delegate로 받고 테스트가 진행 되어야 한다.


XCTest case 함수에서
XCTestExpectation 변수를 전역 변수로 만들고

테스트 케이스 함수에서 네트워크 요청 후
wait(for: [expectation], timeout: 10.0)
위와 같은 코드로 대기를 하게 한다.

XCAssertEqual() 메서드든 wait 코드 아래에 위치 하게 한다.

네트워크 클래스의 delegate 응답 결과를 처리 하는 protocol 메서드에서
expectation.fulfill() 을 호출 하여 대기를 풀어 준다.

그럼 wait이 풀리고 XCAssertEqual에서 테스트 판단이 이루어진다.

말로 설명한 TestCase 코드는 다음과 같다.

let expectation = XCTestExpectation(description: "Network API TEST")
    func testLogin() {
        // 1. given

        // 2. when
        network.login = Network.Login(aId: "choijh", aPassword: "1234567a")
        network.request(API: Network.API.Login, delegate: self)

        wait(for: [expectation], timeout: 10.0)

        // 3. then
        XCTAssertEqual( self.success, true, "Login success")
    }
    
    func testLoginFail() {
        // 1. given
        
        // 2. when
        network.login = Network.Login(aId: "choijh", aPassword: "a")
        network.request(API: Network.API.Login, delegate: self)
        
        wait(for: [expectation], timeout: 10.0)
        
        // 3. then
        XCTAssertEqual( self.success, false, "Login fail wrong password")

    }
    
    func onReceiveSuccessFail(_ success: Bool, api: Network.API) {
        self.success = success
        expectation.fulfill()

    }