Mocking class methods in Objective-C

If you ever find yourself shying away from class methods in your Objective-C designs on the grounds that they reduce the testability of your code, think again:

- (void)testDateSwizzling
{
	Method originalDate = class_getClassMethod([NSDate class], @selector(date));
	Method mockDate = class_getInstanceMethod([self class], @selector(mockDate));
	method_exchangeImplementations(originalDate, mockDate);
	STAssertEquals([NSDate date], [NSDate distantPast], @"Should have mocked method");
	method_exchangeImplementations(mockDate, originalDate);
}

- (NSDate *)mockDate
{
	return [NSDate distantPast];
}

This allows you to substitute your own implementation for a class method, using the magic of Objective-C’s runtime library. I’m going to have a look at how this could be packaged up for OCMock to make the syntax a little nicer, but I’m already using it wherever it simplifies my APIs (NSDates in particular) and wherever I can’t or don’t want to refactor third-party libraries.

This entry was posted in Objective-C. Bookmark the permalink.

One Response to Mocking class methods in Objective-C

  1. Thom.

    You rule. Thankyou so much for pointing this out. As a newbie to Cocoa trying to get his app properly tested I’d hit a roadblock in trying to figure out how to properly mock out the date class method of NSDate.

    I had no idea that this runtime library even existed. Thank goodness I Googled before trying to wangle my own half baked solution involving rewriting half my application. And this will simplify loads of my existing code. I’ve no idea why I didn’t know of this sooner. *slaps own forehead*.

    Once again, you rule. Thanks for putting this out there for newbies like me.

    John

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>