Patrón de layout asynchronous comprobable en Swift

Estoy aprendiendo el desarrollo controlado por testing en Swift. Llegué a una panetworking cuando me di count de que el patrón de delegado que uso regularmente para requestes asincrónicas es difícil de probar. Aprendí que si algo es difícil de probar, el patrón de layout detrás de la implementación podría ser mejor. Esto me confunde porque creo que el patrón de delegado que estoy usando es común y me pregunto cómo otros se han ocupado de este problema.

El patrón:

Escribí un service, que ejecuta una request asíncrona en una function estática que toma una instancia de delegado. La instancia delegada se ajusta a un protocolo que requiere la implementación de un método de éxito y falla. He creado un ejemplo que golpea a Google.com. Ignore los problemas de security de tipo en este ejemplo. El código real que estoy ejecutando para llegar a un punto final y analizar JSON es más seguro. Solo quería presentar un fragment de código muy pequeño para describir el problema que está causando dificultades durante las testings:

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.shanetworkingSession().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)") } } } } 

Aquí está la testing que ilustra el problema:

 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 :(") } } } 

El problema surge en las dos líneas .fulfill() . Recibo el siguiente error de Xcode:

La statement de estructura no puede cerrarse sobre el valor 'responseExpectation' definido en el ámbito externo

Entiendo el error, pero no estoy seguro de qué ajustar … ¿Hay una solución para esto que puedo utilizar en la testing, o hay un patrón mejor (fácilmente comprobable) para las devoluciones de llamada asíncronas de lo que estoy intentando? Si conoce una solución mejor comprobable, ¿le importaría tomarse el time de escribir un ejemplo?

Sí, no puede cerrar las variables definidas fuera de struct, a la solución alternativa, necesitamos usar cierres / funciones y pasarla a la estructura. Los methods en struct pueden invocarlo cuando reciben la respuesta.

  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: No pude probar esto, por favor testing y avísame.