I am learning Test Driven Development in Swift. I hit the wall when I realized that the delegate pattern that I regularly use for asynchronous requests is hard to verify. I learned that if something is difficult to test, the design of an implementation scheme might be better. This is confusing to me because I think the delegate template I use is shared, and I wonder how others handled this problem.
Sample:
I wrote a service that executes an asynchronous request in a static function that accepts a delegate instance. The delegate instance conforms to a protocol that requires the implementation of a success and failure method. I came up with an example that lands on Google.com. In this example, ignore type security issues. The actual code that I run to get to the endpoint and parse the JSON is safer. I just wanted to come up with a very small piece of code to portray a problem causing testing difficulties:
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)")
}
}
}
}
Here is a test that illustrates the problem:
class AsyncTestingTests: XCTestCase {
func testExample() {
let responseExpectation = expectationWithDescription("Got google response!")
struct GoogleDelegate: GoogleServiceDelegate {
func gotGoogle(str: String) {
responseExpectation.fulfill()
}
func gotError(str: String) {
responseExpectation.fulfill()
}
}
let myGoogleServiceDelegate = GoogleDelegate()
GoogleService.getGoogle(myGoogleServiceDelegate)
waitForExpectationsWithTimeout(5) { _ in
print("Never got a response from Google :(")
}
}
}
The problem occurs in two lines .fulfill(). I get the following error from Xcode:
Structure declaration cannot close the value of "responseExpectation" defined in the outer scope
, , ... , , ( ) , , ? , , ?