Unit Testing and Mocking for iPhone Apps

Posted by Doug Fri, 06 Feb 2009 20:54:00 GMT

This was so much harder than I expected it to be. I’m new to Objective-C, but a long time TDD-er with Ruby. Being able to write unit tests and mocks is an integral part of any language I work with now. After much searching and trial and error I got it to work.

First, starting with a new iPhone application I followed these directions on how to get it setup. The Sen:Te guys are who wrote OCUnit in the first place. There are other directions out there, but don’t let them lead you astray. XCode 3 doesn’t support unit testing iPhone applications out of the box. Most of the directions for setting up unit testing is for straight Mac OS X Cocoa apps and not iPhone apps. The gist of the directions are:

  • Add a new target based on Mac OS X Cocoa Unit Test Bundle.
  • In the new test target’s inspector window, whack all the “User-Defined Settings” in the new build tab’s settings.
  • Also delete the ‘‘Other Linker Flags’ setting.
  • In the General tab, add a dependency to the SenTestingKit.framework. Here’s where it gets tricky. Don’t just add any SenTestingKit.framework. You need to add the one from:
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.sdk/Developer/Library/Frameworks/SenTestingKit.framework * Now open the inspector for your application’s main target and set a direct dependency between it and the test target. That will make the tests build and run every time you build the app. Test failure causes a build failure for your main target.

I also added a “Unit Tests” group/folder to the project as a place to store my tests separate from my classes. When you want to create a new test, you simply add a new file and choose the “Objective-C test case class” template. Make sure you add it to the test target and not your main application target.

So that gives you unit tests so you can make assertions; but that’s about it. You also need OCMock. I had a little trouble getting this installed and working, but following Mitchell Hasimoto’s notes I was able to get it working. Download the OCMock framework and save it into /Library/Frameworks. Then in you test target’s inspector add it as a dependency. That should be enough. Here’s a little test class that I used to prove to myself it was working:

testTruth.h:

#import <SenTestingKit/SenTestingKit.h>

@interface testTruth : SenTestCase {

}

- (void) testTruth;
- (void)testAcceptsStubbedMethod;

@end

TestTruth.m:

#import "testTruth.h"
#import <OCMock/OCMock.h>

@implementation testTruth

- (void) testTruth {
    STAssertTrue(1 == 1, @"Must be true");
}

- (void)testAcceptsStubbedMethod {
    id mock = [OCMockObject mockForClass:[NSString class]];
    [[mock stub] lowercaseString];
    [mock lowercaseString];
}
@end

Posted in ,  | Tags , ,  | no comments

Copyright 2001 - 2005 by Lathi.net and Doug Alcorn

Creative Commons, Some Rights Reserved Ruby on Rails Developer Powered by Debian GNU/Linux Powered by Typo