[英]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.