refactoring-objective-c-ios-app

2013-03-29T13:00:23.000Z
Tags: objectiv-c iOS refactoring programming

Doing a bunch of refactoring for one of my iOS apps which is starting to get out of control. I have a few view controllers and one main controller with a lot of code to launch/handle different events, the code handles camera, alerts, vibrations, sounds, local notifications etc and some of this code is duplicated and the whole thing is a big nightmare to fix if there is a bug.

Not to mention logic that manages a socket io connection and now also http requests. I stopped adding new features and started thinking about how I can refactor.

At first I thought maybe I can just start to break up the problem into more classes to encapsulate certain functionality and end up with some more reusable classes. However instead of jumping in and doing this surgery, I decided to take a step back and see if there was a way of adding some unit tests.

After some research I found 2 projects ghunit and ocmock to help me setup a suite of tests/mock/stubs functionality and to help me make sure that after my surgery I don't break anything. It took me a while to install the 2 projects and iOS is very picky when adding external libraries and order does count, more about this later.

So to start I will discuss how I installed ghunit and ocmock. First I downloaded ghunit from and unzipped it to my test project. Not sure it matters but I simply renamed the folder to have no spaces from GHUnitIOS 2.frameworkto GHUnitIOS.framework.

Then I created a another test target project within my original project. Next I added the ghunit framework to the test target project. I then added quartzcore.framework, the version of ghunit I am using required it also. Next I went to the new test target ->build settings other linker flags and added -ObjC and -all_load to enable this static library.

Next I deleted all the files in this new project leaving only the supporting files folder alone. Then I updated main.m under supporting file. removed the AppDelegate.h import and updated the UIApplicationMain method's last argument with @"GHUnitIOSAppDelegate". I then ran the test target app and saw the test suite app at this point with no tests.

Next I added 2 simple testcases (a pass and fail) to verify everything is working. I just created a new file under the test target, called it FirsTest and deleted the .h file the file looks like this:

#import <GHUnitIOS/GHUnit.h>
@interface FirstTest : GHTestCase { }
@end
@implementation
FirstTest
- (void)testSimplePass { // Another test}
- (void)testSimpleFail { GHAssertTrue(NO, nil);}
@end

and I ran the app again and got a listing of 2 tests and hit Run on the app and one test passed and one failed. Next I added the ocmock library. Downloaded the library from comes as a dmg file, ran it and copied the ios folder contents to a folder I created under the project and called it lib. Next I added to the project via xcode to the test target.

Then I updated the ->build setting->Header Search Path for the target app to "\$(SRCROOT)/lib" recursive yes. I then added 2 more tests that utilize ocmock to verify everything is working correctly.

The final version of the FirstTest file looks like this: Now I can start to refactor. I know all this upfront work will benefit my refactoring efforts.


- (void)testOCMockPass {
    id mock = [OCMockObject mockForClass:NSString.class];
    [[[mock stub] andReturn:@"mocktest"] lowercaseString];
    NSString *returnValue = [mock lowercaseString];
    GHAssertEqualObjects(@"mocktest", returnValue, @"Should have returned the expected string.");
  }

- (void)testOCMockFail {
    id mock = [OCMockObject mockForClass:NSString.class];
    [[[mock stub] andReturn:@"mocktest"] lowercaseString];
    NSString *returnValue = [mock lowercaseString];
    GHAssertEqualObjects(@"thisIsTheWrongValueToCheck", returnValue, @"Should have returned the expected string.");
  }

Had problems testing actual classes in my target project, tried a few things but nothing really worked, however I was able to simply add the .m file to Build Phase ->compile sources

Last Updated: 5/21/2019, 12:58:44 PM