Always Objective C asynchronous operation more async when in async test
#concurrency#asynchronous#unittest#objective cTL;DR
Always Use - (void)XCA_notify:(XCTAsyncTestCaseStatus)status withDelay:(NSTimeInterval)delay
in async test.
Do async.
Most opeartion can be an async behavior in objective C. So, you code become js-ed.
dispatch_async(dispatch_get_global_queue(<#dispatch_queue_priority_t priority#>, <#unsigned long flags#>), ^(void) {
// bluhbluh codes
dispatch_async(dispatch_get_main_queue(), ^(void) {
// come back codes
});
});
From Objective C's block I got Why js is called the C's next generation. And, you want to write test? Welcome to pandora.
Some operation is too fast to async.
For better consistency reason, I use XCAsyncTestCase
to do async tests, insert [self XCA_notify:XCTAsyncTestCaseStatusSucceeded];
and wait in the end of the test [self XCA_waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:1];
BUT, if you run test like this:
- (void)testAsyncWhatWhat {
[self XCA_notify:XCTAsyncTestCaseStatusSucceeded];
[self XCA_waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:1];
}
Timeout Exception!
use the following instead:
- (void)testAsyncWhatWhat
{
[self XCA_notify:XCTAsyncTestCaseStatusSucceeded withDelay:0.01];
[self XCA_waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:1];
}
Because this operation is so fast. For an illustration, if you fetch something from core data, Its will raise an exception. Your code don't raise? Good, you got a heinsensbug.
Internal of AsyncTestCase
XCA set two property to check async status
_notified
It will set_notified
tono
at first when callXCA_waitForStatus:timeout:
. Set_notified
tono
means to initialize the next async test. It helps to test async status multiple times. ifXCA_notify:
called beforeXCAwaitForStatus:timeout:
, ThenXCAwaitForStatus:timeout:
will initialize at wrong time, and can't detect async._expectedStatus