Reputation: 44352
I've recreated the example from here: http://www.mokacoding.com/blog/testing-callbacks-in-swift-with-xctest/.
I want to test for a timeout using waitForExpectations()
. This should mimic a long running process that has timed out. To do this, I've set a sleep()
command in the called function that is longer than the timeout in waitForExpectations()
.
However, the sleep()
doesn't have any effect. The test always passes. I've tried putting sleep()
before completion(true)
as well but that doesn't change the outcome (i.e., passed test).
Any ideas what I'm doing run to trigger a test failure on timeout?
class SomeService {
func doSomethingAsync(completion: (_ success: Bool) -> ()) {
completion(true)
sleep(5)
}
}
In test class
let service = SomeService()
service.doSomethingAsync { (success) in
XCTAssertTrue(success, "assert is true")
expect.fulfill()
}
waitForExpectations(timeout: 3) { (error) in
if let error = error {
XCTFail("timeout errored: \(error)")
}
}
Upvotes: 2
Views: 6746
Reputation: 7649
Your test passes because you are calling completion
before sleep
, so your expectation is being fulfilled almost immediately - before you wait for 5 seconds; while the completion block is executed asynchronously, it is likely going to finish in under a second.
If you call sleep
insidecompletion
then your test will fail as expected. However, your test may crash if the test is no longer running when expect.fulfill()
is called since expect
may no longer exist by the time it is executed, as it may have been cleaned up as soon as the test fails (about 2 seconds before the expectation will be fulfilled).
class SomeService {
func doSomethingAsync(completion: (_ success: Bool) -> ()) {
DispatchQueue.main.async {
completion(true)
}
}
}
Test:
let service = SomeService()
service.doSomethingAsync { (success) in
XCTAssertTrue(success, "assert is true")
sleep(5)
expect.fulfill()
}
waitForExpectations(timeout: 3) { (error) in
if let error = error {
XCTFail("timeout errored: \(error)")
}
}
Upvotes: 1