OK. I looked around, and didn't find an exact answer to my issue.
I am trying to test a timeout handler in a unit test (not the main run).
The issue seems to be that the [NSRunLoop mainRunLoop]
is not running in unit tests the way it does in the standard Run.
I do my timeouts in this manner:
NSTimer *pTimeoutHandler = [NSTimer
timerWithTimeInterval:2.0
target:self
selector:@selector(timeoutHandler:)
userInfo:nil
repeats:NO
];
[[NSRunLoop mainRunLoop] addTimer:pTimeoutHandler forMode:NSRunLoopCommonModes];
This works in the standard run. This is the recommended manner of setting a timeout.
However, in the Test run, this doesn't work. The timeoutHandler:(NSTimer*)timer
routine is never called.
It appears as if something is interfering with the run loop.
Is there any way for me to get the timeout to work in both run and unit test?
When you use timers and the main runloop, you will need to manually run the runloop:
while (continueCondition || !time_way_over_timeout) {
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
where continueCondition
could be some flag that indicates that the timeout handler was invoked and time_way_over_timeout
a comparision of the current time with a pre-calulated maximum execution time (so you can handle a "timeout of timout test" for your unit test ^^)
Also see this blog post about asynchronous unit testing: http://dadabeatnik.wordpress.com/2013/09/12/xcode-and-asynchronous-unit-testing/
Looks something like this in Swift 3.0 with XCTest.
// somebody has to call the .fulfill() method on this variable
// to the expectation will fail after 25 seconds
var asyncExpectation : XCTestExpectation!
func testExample() {
asyncExpectation = expectation(description: "longRunningFunction")
self.waitForExpectations(timeout: 25.0) { (error) in
if let error = error {
print("Error \(error)")
}
}
// more stuff here
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With