The basic idea is that your test has to create an expectation:
let e = expectation(description: "testGetUsers")
And then when your asynchronous method is done, fulfill that expectation:
e.fulfill()
And then, of course, your test has to, after initiating the asynchronous tasks, wait for the expectations:
waitForExpectations(timeout: 10)
But, obviously, you need to know when your function is done. I would suggest giving it an optional completion handler:
func firePendingEvent(completion: (() -> Void)? = nil) {
let group = DispatchGroup()
for analyticItem in eventQueue {
group.enter()
eventPriorityQueue.addOperationToQueue(operation: BlockOperation {
self.analyticsObserver?.logEvent(event: analyticItem)
group.leave()
}, priority: .normal)
}
eventQueue.removeAll()
if let completion = completion {
group.notify(queue: .main, execute: completion)
}
}
(Note, I personally refrain from mutating an array as I iterate through it, so I add all the tasks to the queue and defer the removeAll
until I am no longer iterating.)
Anyway, you can now write your test:
func testFirePendingEvents() {
let e = expectation(description: "testGetUsers")
foo.firePendingEvent {
XCAssert(…) // do whatever tests are appropriate
e.fulfill()
}
waitForExpectations(timeout: 10)
}
But, because that completion handler is optional, and defaults to nil
, you don't have to change the rest of your code that isn't availing itself of the new completion handler.
Personally, I would add a parameter to that completion handler closure to pass back whatever value you want to test, but there wasn’t enough in the question to know what result you are testing.