Reputation: 12915
I encountered an issue when I'm writing XCTestCase. I'm working on a client/server application. User can only start to use the system when the application login to the server which is automatically done in:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// connect to server and login
[mySys login:^{
login = YES;
}];
}
All my test case can only be run when the login flag is YES. Because the login may take sometimes. That means I have to let all my tests to wait at least for a period of time (for example, 30 second). It's something like this:
-(void)setUp
{
// Need to be blocked here until timeout !!!
AppDelegate* app = [UIApplication sharedApplication].delegate;
if ( app.login )
{
// quit from the block !!!
}
}
What could be the best strategy to implement this? Thanks
Upvotes: 0
Views: 645
Reputation: 12915
Thanks for Jeff's answer. I learned a lot from the video. After my serious consideration, I'm still going to test my Rest API in unit test. Mainly because I'm the one who work on the Rest API. I want to test my client and server at the same time. I'll definitely go with Jeff's idea if I'm working on a big project and the models are more complicated.
Finally I'll show my solution: (Wait for a operation finished before starting the test). The idea is to write a base class who inherits from XCTextCase. And I'm using NSNotification to broadcast the login event.
- (void)setUp
{
[super setUp];
AppDelegate* app = [UIApplication sharedApplication].delegate;
if ( ![app isLogin] )
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onLogin:) name:NOTIFICATION_LOGIN object:nil];
NSDate* loopUntil = [NSDate dateWithTimeIntervalSinceNow:10];
NSDate *dt = [NSDate dateWithTimeIntervalSinceNow:0.1];
while (!self.bCheckIn && [loopUntil timeIntervalSinceNow] > 0) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:dt];
}
}
}
- (void)tearDown
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:NOTIFICATION_LOGIN object:nil];
[super tearDown];
}
- (void)onLogin:(NSNotification *)notification
{
self.bLogin = YES;
}
Upvotes: 0
Reputation: 9042
Create a mock login, that doesn't actually call to the server, and takes a completion block with the login already set to YES. I recommend eBay's tech talk on TDD, it covers this very scenario.
I recommend watching the whole video, but here is a link to the specific part: https://www.youtube.com/watch?v=_CeWMxzB1SI#t=1805
Upvotes: 2