In the UI class I have a method that accesses UI elements, and hence is supposed to force itself onto a main thread. Here's a minimal example of what I mean:
class SomeUI {
func doWorkOnUI() {
guard Thread.isMainThread else {
DispatchQueue.main.async {
self.doWorkOnUI()
}
return
}
print("Doing the work on UI and running on main thread")
}
}
In the tests, of course there's no problem to test the case when doWorkOnUI() is already running on main thread. I just do this:
func testWhenOnMainThread() {
let testedObject = SomeUI()
let expectation = XCTestExpectation(description: "Completed doWorkOnUI")
DispatchQueue.main.async {
testedObject.doWorkOnUI()
expectation.fulfill()
}
wait(for: [expectation], timeout: 10.0)
// Proceed to some validation
}
That is: force execution onto main thread. Wait for it to complete. Do some checks.
But how to test the opposite case, i.e. ensure that function forced itself to run on main thread when called from the background thread?
For example if I do something like:
...
DispatchQueue.global(qos: .background).async {
testedObject.doWorkOnUI()
expectation.fulfill()
}
...
I just tested that function got executed from the background thread. But I didn't explicitly check that it ran on main thread. Of course, since this function accesses UI elements, the expectation is that it crashes if not forced on main thread. So is "no crash" the only testable condition here? Is there anything better?