簡體   English   中英

Swift中可測試的異步設計模式

[英]Testable Asynchronous Design Pattern in Swift

我正在學習Swift中的測試驅動開發。 當我意識到我經常用於異步請求的委托模式很難測試時,我碰壁了。 我已經了解到,如果某些事情難以測試,實施背后的設計模式可能會更好。 這讓我感到困惑,因為我認為我使用的委托模式很常見,我想知道其他人是如何處理這個問題的。

模式:

我編寫了一個服務,它在靜態函數中執行異步請求,該函數接受委托實例。 委托實例符合需要實現成功和失敗方法的協議。 我設計了一個擊中Google.com的例子。 請忽略此示例中的類型安全問題。 我正在運行以命中端點並解析JSON的實際代碼更安全。 我只是想提出一小段代碼來描述在測試時造成困難的問題:

protocol GoogleServiceDelegate {
    func gotGoogle(str: String);
    func gotError(str: String);
}

struct GoogleService {
    static func getGoogle(delegate: GoogleServiceDelegate) {
        let url: NSURL! = NSURL(string: "http://google.com")
        NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in
            if let data = data {
                let str: NSString! = NSString(data: data, encoding: NSUTF8StringEncoding)
                delegate.gotGoogle(str as String)
            } else {
                delegate.gotError("\(error)")
            }
        }
    }
}

這是測試說明問題:

class AsyncTestingTests: XCTestCase {

    func testExample() {
        let responseExpectation = expectationWithDescription("Got google response!")

        struct GoogleDelegate: GoogleServiceDelegate {
            func gotGoogle(str: String) {
                // expectations about response
                responseExpectation.fulfill()
            }

            func gotError(str: String) {
                // expectations about error
                responseExpectation.fulfill()
            }
        }

        let myGoogleServiceDelegate = GoogleDelegate()
        GoogleService.getGoogle(myGoogleServiceDelegate)

        waitForExpectationsWithTimeout(5) { _ in
            print("Never got a response from Google :(")
        }
    }
}

問題出現在兩個.fulfill()行上。 我從Xcode收到以下錯誤:

結構聲明不能關閉外部作用域中定義的值“responseExpectation”

我理解錯誤,但我不確定要調整什么...有沒有可以在測試中使用的解決方法,或者是否有比我正在嘗試的異步回調更好(易於測試)的模式? 如果你知道一個更好的可測試解決方案,你會介意花時間寫下一個例子嗎?

是的,你不能關閉在struct之外定義的變量,為了解決方法,我們需要使用閉包/函數並將它傳遞給struct。 struct中的方法可以在收到響應時調用它。

    func testExample() {
      let responseExpectation = expectationWithDescription("Got google response!")

//Let a function capture the fulfilling of the expectation
      func fullFillExpectation(){

        responseExpectation.fullFill()
      }

      struct GoogleDelegate: GoogleServiceDelegate {

        var fullFiller : (()->Void)!
        func gotGoogle(str: String) {
          // expectations about response via invoke the closure
          fullFiller()
        }

        func gotError(str: String) {
          // expectations about error - invoke the closure
          fullFiller()
        }
      }

      //Create the delegate with full filler function.
      let myGoogleServiceDelegate = GoogleDelegate(fullFiller: fullFillExpectation)
      GoogleService.getGoogle(myGoogleServiceDelegate)

      waitForExpectationsWithTimeout(5) { _ in
        print("Never got a response from Google :(")
      }
    }
    }

PS:我無法測試,請測試並告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM