Mocking Class Method in Objective-C

Once in a while, when testing your Objective-C code, you want or have to mock a class method. Or you want to replace the implementation of a class method. The following code replaces the implementation of originalClassMethod of SomeClass with the implementation of mockClassMethod of MockClass:

Method mockMethod = class_getInstanceMethod([MockClass class], @selector(mockClassMethod));
IMP mockImpl = method_getImplementation(mockMethod);
Method originalMethod = class_getClassMethod([SomeClass class], @selector(originalClassMethod));
IMP originalImpl = method_setImplementation(originalMethod, testImpl);

Don’t forget to import objc/runtime.h.


New Objective-C Boxing Rocks!

The new boxing feature of the Objective-C runtime rocks! In tests, for instance, I don’t have to write

assertThatBool([obj someBoolReturningMethod], equalToBool(YES));

but I can write the following

assertThat(@([obj someBoolReturningMethod]), is(@(YES)));

Note that I’m using OCHamcrest or my fork which can handle NSSize, NSRange, NSRect and NSPoint. My fork is probably broken for iOS.

It works also for other primitive types like int.


Continuous Integration for Cocoa using Jenkins, Part II

Outdated: See Continuous Integration for Cocoa Reloaded

Some time ago, I wrote about how to use Jenkins for Cocoa/iPhone projects. Back then, I used GHUnit which can produce JUnit test results XML files. Recently, I found OCUnit2JUnit which converts OCUnit results to JUnit result XML format. Thus, no more GHUnit. Do the following

xcodebuild -target NAME_OF_TARGET -configuration Debug clean test | /PATH/TO/ocunit2junit.rb


xcodebuild -scheme NAME_OF_SCHEME -configuration Debug clean test | /PATH/TO/ocunit2junit.rb

Note that you may have to copy the scheme definitions before executing xcodebuild, see the post How to Use Subprojects with Xcode and Jenkins.

Add “Publish JUnit test result report” step as a post-build action with **/test-reports/*.xml and you’re set!


How to Use Subprojects with Xcode and Jenkins

Assume, you have an Xcode project Parent and another project Child, which is registered as a subproject of Parent. Let’s further assume that Child is registered as a Git submodule of Parent. Imagine that you want to use Jenkins for continuous integration for the project Parent. Do the following:

  1. Make sure that xcuserdata folder in Parent.xcodeproj is included in the Git repository.
  2. Download ocunit2junit.rb. Yay, you don’t need GHUnit anymore!
  3. Create a free-style job in Jenkins and add an “Execute shell” step with the following
    git submodule init
    git submodule update
    git submodule -q foreach git pull -q origin master
    cp -r Parent.xcodeproj/xcuserdata/YOUR_USER_NAME.xcuserdatad Parent.xcodeproj/xcuserdata/JENKINS_USER_NAME.xcuserdatad
    xcodebuild -scheme NAME_OF_OCUNIT_SCHEME -configuration Release clean test | /PATH/TO/ocunit2junit.rb
  4. Add “Publish JUnit test result report” post-build action:
  5. Voilà!

Argument Captor for Objective-C

For my small projects Qmind and Qdesktop I needed a Objective-C counterpart of Mockito’s ArgumentCaptor. As far as I can see, OCHamcrest or OCMockito do not offer this functionality. Thus, I wrote an OCHamcrest matcher which does the job: ArgumentCaptor.zip


ArgumentCaptor *captor = argCaptor();

[someMock someMessage:someArgument];
[verify(someMock) someMessage:captor];

id argument = captor.argument;
assertThat(argument, is(someArgument));

BTW, I’m using the ARC.

Tags: cocoa testing