-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Integration style tests are tricky because your test code runs within the runloop, so new events pushed onto the runloop during your test will not run by default. This can lead to unexpected behaviour, because code that normally runs in your real app doesn't get an opportunity to do so.
When you tap a button on ViewController A that pushes a UIViewController B onto the stack, the lifecycle methods of B such as viewWillAppear and viewDidLoad are normally called. From your tests this won't happen automatically, so you will have to either manually tick the runloop, or call them yourself. Beware that if you don't call them, then your navigationController can end up in a corrupt state and see error messages like Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted
To tick the runloop, simply get the current runloop and tell it to run until the current time. For example, you can make a helper to achieve this:
void(^tickRunLoop)() = ^{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
};
Then, assuming that tapping the earthquakesButton transitions to a viewController, and that viewController sets it's title in viewDidLoad, then your test looks something like this:
it(@"displays the title correctly if you tick the runloop", ^{
[controller.earthquakesButton sendActionsForControlEvents:UIControlEventTouchUpInside];
navigationController.topViewController.title should be_nil;
tickRunLoop();
navigationController.topViewController.title should equal(@"Earthquakes!");
});
See MenuViewControllerSpec.mm for an example of this.