4thSpace
4thSpace

Reputation: 44352

How to trigger failed test on timeout with waitForExpectations()?

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

Answers (1)

Oletha
Oletha

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

Related Questions