2

I understand CLGeocoder().reverseGeocodeLocation(...) will be executed in another thread, so that completionHandler will be executed in the main thread once it successfully gets the result from Apple server. The problem is I cannot see what happened in the completionHandler when I'm using in unit tests(when I build the framework), but it works fine in the Application. For simplify my question, I extract the asynchronous part from my codes in unit test as follows:

func testGeo() {
    var location = CLLocation(latitude: 45.0, longitude: 135.5)
    var semaphore = dispatch_semaphore_create(0)
    println("------fetch----->")
    CLGeocoder().reverseGeocodeLocation(location, completionHandler:{ (placemarks, error) -> Void in
        if error != nil {
            println("[ERROR]: \(error) in getPlacemarkFromLocation")
        }

        if placemarks.count > 0 {
            println("[SUCCESS] get the placemark!")
            let pm = placemarks[0] as! CLPlacemark
            self.displayLocationInfo(pm)
        } else {
            println("[ERROR] get 0 placemarks in getPlacemarkFromLocation")
        }
        dispatch_semaphore_signal(semaphore)
    })
    println("------wait--- -->")
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}

When I do this unit test, it seems to not execute the completionHandler because nothing to print in the console. Every time I use asynchronous api, I cannot get the return value successfully in my unit test. I need to use unit test to make sure all the pipe of my framework works well. This gonna make me crazy... How can I fix this problem? Thanks a lot :)

James Fu
  • 444
  • 1
  • 8
  • 21

1 Answers1

1

The problem is because the test functions exit before the completion handler finishes.

From Xcode 6, Apple shipped an asynchronous testing facility called XCTestExpectation. This thing enables us to wait some time before going out of scope. Usage is as simple as:

    let expect = self.expectationWithDescription("exp")
    sc.asyncCall(para) { (data, error) in

        XCTAssertNotNil(data)

        expect.fulfill()
    }

    self.waitForExpectationsWithTimeout(1) { (error) in
        guard error == nil else {
            XCTAssert(false)
            NSLog("Timeout Error.")
            return
        }
    }
strongwillow
  • 328
  • 2
  • 13