Asynchronous unit testing with OCMock
Thursday, November 5, 2009 at 10:29PM I've recently been using OCMock more and more. It's a great mocking framework for writing unit test for the mac or the iPhone.
When I mock delegate objects which wait for asynchronous callbacks I use this handy utility method
Update
There was a bug in here which made the utility return early, no matter how long the delay was. I've updated the code to fix the bug.
//
// TestUtils.h
//
// Created by Hans Sjunnesson on 2009-11-05.
//
#import <Foundation/Foundation.h>
#import <OCMock/OCMock.h>
@interface TestUtils : NSObject {
}
/*!
@method waitForVerifiedMock:delay:
@abstract Runs the current run loop for as long as specified by the delay, or until the mockobject verifies.
@param mock the OCMockObject to verify.
@param delay the time to wait until the mock is verified, in seconds.
*/
+ (void)waitForVerifiedMock:(OCMockObject *)mock delay:(NSTimeInterval)delay;
@end
And the implementation:
//
// TestUtils.m
//
// Created by Hans Sjunnesson on 2009-11-05.
//
#import "TestUtils.h"
@implementation TestUtils
+ (void)waitForVerifiedMock:(OCMockObject *)inMock delay:(NSTimeInterval)inDelay
{
NSTimeInterval i = 0;
while (i < inDelay)
{
@try
{
[inMock verify];
break;
}
@catch (NSException *e) {}
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
i+=0.5;
}
}
@end
Here's an example of testing 'NSURLConnection' trying to connect to google.com.
@implementation NSObject (NSURLConnectionDelegate)
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {}
@end
- (void)testShouldConnect {
id mock = [OCMockObject mockForClass:[NSObject class]];
NSURL *url = [NSURL URLWithString:@"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:mock startImmediately:NO];
[[mock expect] connection:connection didReceiveResponse:OCMOCK_ANY];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[connection start];
// Wait for five seconds
[TestUtils waitForVerifiedMock:mock delay:5.0];
STAssertNoThrow([mock verify], @"Should be able to connect to google.");
}
objective-c,
programming