2

I'm trying to use the new DispatchGroup mechanism with an OperationQueue so that my unit test will wait for completion. After watching the WWDC videos I've only seen how to use groups with async calls from regular dispatches. How do I get the same functionality with Operation Queues?

This is my test without any pauses (and therefore it passes without stopping to test assertion in completion block):

func testAlertOperationPresentsMessage() {
    var testSuccess = false
    let action: AlertClosure = { action in
        testSuccess = true
    }

    let alert = AlertOperation(title: "Test", message: "Message", context: nil, action: action)

    alert.completionBlock = { XCTAssert(testSuccess) }

    OperationQueue.main.addOperation(alert)
}

In previous versions of Swift I would've done something like this:

func testAlertOperationPresentsMessage() {
    var testSuccess = false
    let action: AlertClosure = { action in
        testSuccess = true
    }

    let alert = AlertOperation(title: "Test", message: "Message", context: nil, action: action)

    let group = dispatch_group_create()
    dispatch_group_enter(group)
    alert.completionBlock = { dispatch_group_leave(group) }

    OperationQueue.main.addOperation(alert)
    dispatch_group_wait(group, FOREVER...) {
        XCTAssert(testSuccess)
    }
}

In Swift 3, I think I'm meant to do something like this...

func testAlertOperationPresentsMessage() {
    var testSuccess = false
    let action: AlertClosure = { action in
        testSuccess = true
    }

    let alert = AlertOperation(title: "Test", message: "Message", context: nil, action: action)

    let group = DispatchGroup()
    OperationQueue.main.async(group: group) { 
        alert.start()
    }
    group.notify(queue: DispatchQueue.main) { XCTAssert(testSuccess) }
}

or:

func testAlertOperationPresentsMessage() {
    var testSuccess = false
    let action: AlertClosure = { action in
        testSuccess = true
    }

    let alert = AlertOperation(title: "Test", message: "Message", context: nil, action: action)

    alert.completionBlock = { XCTAssert(testSuccess) }

    let queue = OperationQueue()
    queue.addOperation(alert)
    queue.waitUntilAllOperationsAreFinished()
//    OperationQueue.main.addOperation(alert)

}

I use the following type alias:

typealias AlertClosure = ((UIAlertAction) -> Void)?

If needed I can include code for AlertOperation, but that doesn't seem necessary at this point. Essentially, the AlertOperation presents a message and then performs the AlertClosure when USER taps OK button.

Mercutio
  • 1,152
  • 1
  • 14
  • 33

0 Answers0