I'm using XCTest
and OCMock
to write unit tests for an iOS app, and I need direction on how to best design a unit test that verifies that a method results in an NSTimer
being started.
Code under test:
- (void)start {
...
self.timer = [NSTimer timerWithTimeInterval:1.0
target:self
selector:@selector(tick:)
userInfo:nil
repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
...
}
What I want to test is that the timer is created with the right arguments, and that the timer is scheduled to run on the run loop.
I've thought of the following options that I am not happy with:
- Actually wait for the timer to fire. (Reason I don't like it: terrible unit testing practice. It's more like a slow integration test.)
- Extract the timer starting code into a private method, expose that private method in a class extension file to the unit tests, and use a mock expectation to verify that the private method gets called. (Reason I don't like it: it verifies that the method gets called, but not that the method actually sets up the timer to run correctly. Also, exposing private methods is not a good practice.)
- Provide a mock
NSTimer
to the code under test. (Reason I don't like it: can't verify that it actually gets scheduled to run because timers are started via the run loop and not from someNSTimer
start method.) - Provide a mock
NSRunLoop
and verify thataddTimer:forMode
: gets called. (Reason I don't like it: I'd have to provide an interface into the run loop? That seems wacky.)
Can someone provide some unit testing coaching?